move to front of array

Discussion in 'Ruby' started by Payton Swick, Dec 21, 2005.

  1. Payton Swick

    Payton Swick Guest

    Hi,

    I have an array of Strings, and I'd like to find one of the items by
    Regexp, then move that item to the front of the array, eg:

    array = %w(a B c d Cool e f G)
    array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    }))) if array.find { |i| i =~ /cool/i }

    Better/cleaner/shorter ways to do it?

    -Payton
     
    Payton Swick, Dec 21, 2005
    #1
    1. Advertising

  2. Payton Swick wrote:

    > I have an array of Strings, and I'd like to find one of the items by
    > Regexp, then move that item to the front of the array, eg:
    >
    > array = %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    > }))) if array.find { |i| i =~ /cool/i }



    In 1.8.x:

    require 'enumerator'
    if f = array.enum_for:)each_index).find { |i| array =~ /cool/i }
    array.unshift array.delete_at(f)
    end


    In 1.9.x you can do:

    array.unshift array.delete_at(array.index { |x| x =~ /cool/i })

    --
    Florian Frank
     
    Florian Frank, Dec 21, 2005
    #2
    1. Advertising

  3. Payton Swick

    Jacob Fugal Guest

    On 12/21/05, Payton Swick <> wrote:
    > Hi,
    >
    > I have an array of Strings, and I'd like to find one of the items by
    > Regexp, then move that item to the front of the array, eg:
    >
    > array =3D %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =3D~ /cool/i
    > }))) if array.find { |i| i =3D~ /cool/i }
    >
    > Better/cleaner/shorter ways to do it?
    >
    > -Payton


    array =3D %w(a B c d Cool e f G)
    if cool =3D array.find { |i| i =3D~ /cool/i }
    array.delete(cool)
    array.unshift(cool)
    end

    ?

    Jacob Fugal
     
    Jacob Fugal, Dec 21, 2005
    #3
  4. On Dec 21, 2005, at 3:08 PM, Payton Swick wrote:

    > Hi,
    >
    > I have an array of Strings, and I'd like to find one of the items
    > by Regexp, then move that item to the front of the array, eg:
    >
    > array = %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/
    > i }))) if array.find { |i| i =~ /cool/i }
    >
    > Better/cleaner/shorter ways to do it?
    >
    > -Payton
    >


    I don't know about shorter but...

    require 'enumerator'
    array = %w(a B c d Cool e f G)
    index = array.to_enum:)each_index).find { |i| array =~ /cool/i }
    array.unshift( array.delete_at( index ) )
     
    Logan Capaldo, Dec 21, 2005
    #4
  5. Payton Swick wrote:
    > Hi,
    >
    > I have an array of Strings, and I'd like to find one of the items by
    > Regexp, then move that item to the front of the array, eg:
    >
    > array = %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    > }))) if array.find { |i| i =~ /cool/i }
    >
    > Better/cleaner/shorter ways to do it?


    This should work (but without error checking):

    array.unshift(array.delete(array.grep(/cool/i).first))

    > -Payton



    E


    --
    Posted via http://www.ruby-forum.com/.
     
    Eero Saynatkari, Dec 21, 2005
    #5
  6. Payton Swick

    Dan Diebolt Guest

    --0-302192896-1135198321=:86581
    Content-Type: text/plain; charset=iso-8859-1
    Content-Transfer-Encoding: quoted-printable

    Try this:
    =20
    array1 =3D %w(a B c d Cool e f G)
    array1.partition {|i| i =3D~ /cool/i}
    array2=3Darray1.partition {|i| i =3D~ /cool/i}
    array2.flatten #or array2.flatten!

    __________________________________________________
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around=20
    http://mail.yahoo.com=20
    --0-302192896-1135198321=:86581--
     
    Dan Diebolt, Dec 21, 2005
    #6
  7. On Dec 21, 2005, at 12:08 PM, Payton Swick wrote:

    > Hi,
    >
    > I have an array of Strings, and I'd like to find one of the items
    > by Regexp, then move that item to the front of the array, eg:
    >
    > array = %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/
    > i }))) if array.find { |i| i =~ /cool/i }
    >
    > Better/cleaner/shorter ways to do it?
    >
    > -Payton
    >


    array.unshift(array.delete_at(array.index("Cool")))

    # => ["Cool", "a", "B", "c", "d", "e", "f", "G"]

    -Ezra
     
    Ezra Zygmuntowicz, Dec 21, 2005
    #7
  8. Payton Swick

    Jacob Fugal Guest

    On 12/21/05, Dan Diebolt <> wrote:
    > Try this:
    >
    > array1 =3D %w(a B c d Cool e f G)
    > array1.partition {|i| i =3D~ /cool/i}
    > array2=3Darray1.partition {|i| i =3D~ /cool/i}
    > array2.flatten #or array2.flatten!


    So something like:

    array =3D %w(a B c d Cool e f G)
    array =3D array.partition{ |el| el =3D~ /cool/i }.flatten

    That certainly would work (assuming that only one element matches the
    condition), and has a certain elegance. I wonder if there's a
    significant performance penalty?

    It also gave me this idea:

    class Array
    def bubble_up
    score =3D lambda{ |a| (yield a) ? -1 : 1 }
    self.sort_by { |a,b| score[a] <=3D> score }
    end

    def bubble_up!( &proc )
    self.replace(self.bubble_up( &proc ))
    end
    end

    array =3D array.bubble_up! { |el| el =3D~ /cool/i }

    Jacob Fugal
     
    Jacob Fugal, Dec 21, 2005
    #8
  9. Jacob Fugal wrote:
    > On 12/21/05, Payton Swick <> wrote:
    > > Hi,
    > >
    > > I have an array of Strings, and I'd like to find one of the items by
    > > Regexp, then move that item to the front of the array, eg:
    > >
    > > array = %w(a B c d Cool e f G)
    > > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    > > }))) if array.find { |i| i =~ /cool/i }
    > >
    > > Better/cleaner/shorter ways to do it?
    > >
    > > -Payton

    >
    > array = %w(a B c d Cool e f G)
    > if cool = array.find { |i| i =~ /cool/i }
    > array.delete(cool)
    > array.unshift(cool)
    > end


    array.unshift(array.delete("Cool"))

    Regards,

    Dan
     
    Daniel Berger, Dec 21, 2005
    #9
  10. Payton Swick

    Dan Diebolt Guest

    --0-840281129-1135201148=:26597
    Content-Type: text/plain; charset=iso-8859-1
    Content-Transfer-Encoding: quoted-printable

    >That certainly would work (assuming that only one element matches the

    condition),
    =20
    seems to work on multiple matches:
    =20
    array =3D %w(a B c d Cool e f G Cool Cooler)
    =3D> ["a", "B", "c", "d", "Cool", "e", "f", "G", "Cool", "Cooler"]
    array =3D array.partition{ |el| el =3D~ /cool/i }.flatten!
    =3D> ["Cool", "Cool", "Cooler", "a", "B", "c", "d", "e", "f", "G"]

    I was uncertain about needing parenthesis before applying flatten but it =
    makes perfect sense:
    =20
    array =3D (array.partition{ |el| el =3D~ /cool/i }).flatten!

    __________________________________________________
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around=20
    http://mail.yahoo.com=20
    --0-840281129-1135201148=:26597--
     
    Dan Diebolt, Dec 21, 2005
    #10
  11. Payton Swick

    Jacob Fugal Guest

    On 12/21/05, Dan Diebolt <> wrote:
    > >That certainly would work (assuming that only one element matches the

    > condition),
    >
    > seems to work on multiple matches:


    Yeah, I realized that as I was working through my variation, but never
    made it back up to change the text. :)

    > I was uncertain about needing parenthesis before applying flatten but it =

    makes perfect sense:
    >
    > array =3D (array.partition{ |el| el =3D~ /cool/i }).flatten!


    You don't need the bang here, however. Since Array#partition will
    always create nested arrays, you won't run into the flatten! returning
    nil bug, but it is still wasted effort to change a temporary array in
    place.

    Jacob Fugal
     
    Jacob Fugal, Dec 21, 2005
    #11
  12. Payton Swick wrote:

    > Hi,
    >
    > I have an array of Strings, and I'd like to find one of the items by
    > Regexp, then move that item to the front of the array, eg:
    >
    > array = %w(a B c d Cool e f G)
    > array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    > }))) if array.find { |i| i =~ /cool/i }
    >
    > Better/cleaner/shorter ways to do it?


    I'm going to do something controversial and suggestion a completely
    imperative method:

    array.each_with_index {|o,i| array.unshift(array.delete_at(i)) if o =~
    /cool/i}

    Oddly, this works with multiple instances of Cool. I take it that
    #each_with_index doesn't miss a beat wrt the modifications.

    Oh, and if you'll be doing it more than once in your code, then put the
    method where it belongs:
    class Array
    def bubble_if!(regex=nil)
    if block_given? then each_with_index {|o,i| unshift(delete_at(i)) if
    yield o}
    else super() {|o| =~ regex}
    end
    end
    end
    array.bubble_if!(/cool/i)

    Devin
    YMMV.
     
    Devin Mullins, Dec 22, 2005
    #12
  13. No inject solution?

    here it is:

    array = %w(a B c d Cool e f G)
    p array.inject([]){|s, o| o =~ /cool/i ? [o, *s] : s << o}

    => ["Cool", "a", "B", "c", "d", "e", "f", "G"]

    cheers

    Simon

    Devin Mullins wrote:
    > Payton Swick wrote:
    >
    >> Hi,
    >>
    >> I have an array of Strings, and I'd like to find one of the items by
    >> Regexp, then move that item to the front of the array, eg:
    >>
    >> array = %w(a B c d Cool e f G)
    >> array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    >> }))) if array.find { |i| i =~ /cool/i }
    >>
    >> Better/cleaner/shorter ways to do it?

    >
    >
    > I'm going to do something controversial and suggestion a completely
    > imperative method:
    >
    > array.each_with_index {|o,i| array.unshift(array.delete_at(i)) if o =~
    > /cool/i}
    >
    > Oddly, this works with multiple instances of Cool. I take it that
    > #each_with_index doesn't miss a beat wrt the modifications.
    >
    > Oh, and if you'll be doing it more than once in your code, then put the
    > method where it belongs:
    > class Array
    > def bubble_if!(regex=nil)
    > if block_given? then each_with_index {|o,i| unshift(delete_at(i)) if
    > yield o}
    > else super() {|o| =~ regex}
    > end
    > end
    > end
    > array.bubble_if!(/cool/i)
    >
    > Devin
    > YMMV.
    >
    >
    >
     
    Simon Kröger, Dec 22, 2005
    #13
  14. Payton Swick

    Dan Diebolt Guest

    --0-718474068-1135249413=:8712
    Content-Type: text/plain; charset=iso-8859-1
    Content-Transfer-Encoding: quoted-printable

    I like it! I used to puzzle over why they named it "inject" but then I re=
    alized that injection is like mainlining a variable through each element =
    of an enum. The injected variable is often used as some type of accumulat=
    or but this convention is not necessary; the injected variable can be use=
    d for any purpose.

    __________________________________________________
    Do You Yahoo!?
    Tired of spam? Yahoo! Mail has the best spam protection around=20
    http://mail.yahoo.com=20
    --0-718474068-1135249413=:8712--
     
    Dan Diebolt, Dec 22, 2005
    #14
  15. Payton Swick

    Payton Swick Guest

    Just for the sake of completeness, here is Devin's suggestion, with
    syntax errors corrected:

    class Array
    def bubble_if!(regex=nil)
    if block_given? then each_with_index {|o,i| unshift(delete_at(i))
    if yield o}
    else bubble_if! {|o| o =~ regex}
    end
    end
    end

    Thanks for the suggestions, everyone!

    -Payton

    Devin Mullins wrote:
    > Payton Swick wrote:
    >
    >> Hi,
    >>
    >> I have an array of Strings, and I'd like to find one of the items by
    >> Regexp, then move that item to the front of the array, eg:
    >>
    >> array = %w(a B c d Cool e f G)
    >> array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/i
    >> }))) if array.find { |i| i =~ /cool/i }
    >>
    >> Better/cleaner/shorter ways to do it?

    >
    >
    > I'm going to do something controversial and suggestion a completely
    > imperative method:
    >
    > array.each_with_index {|o,i| array.unshift(array.delete_at(i)) if o =~
    > /cool/i}
    >
    > Oddly, this works with multiple instances of Cool. I take it that
    > #each_with_index doesn't miss a beat wrt the modifications.
    >
    > Oh, and if you'll be doing it more than once in your code, then put the
    > method where it belongs:
    > class Array
    > def bubble_if!(regex=nil)
    > if block_given? then each_with_index {|o,i| unshift(delete_at(i)) if
    > yield o}
    > else super() {|o| =~ regex}
    > end
    > end
    > end
    > array.bubble_if!(/cool/i)
    >
    > Devin
    > YMMV.
    >
     
    Payton Swick, Dec 22, 2005
    #15
  16. Payton Swick

    Ron M Guest

    Ezra Zygmuntowicz wrote:
    > On Dec 21, 2005, at 12:08 PM, Payton Swick wrote:
    >>
    >> array = %w(a B c d Cool e f G)
    >> array.unshift(array.slice!(array.index(array.find { |i| i =~ /cool/ i
    >> }))) if array.find { |i| i =~ /cool/i }
    >>
    >> Better/cleaner/shorter ways to do it?

    >
    > array.unshift(array.delete_at(array.index("Cool")))



    array.sort_by{|x| x=~/cool/i ? 0 : 1}
     
    Ron M, Dec 23, 2005
    #16
  17. Ron M wrote:

    > array.sort_by{|x| x=~/cool/i ? 0 : 1}


    +1
     
    Devin Mullins, Dec 23, 2005
    #17
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Tom Anderson
    Replies:
    2
    Views:
    1,424
    Joshua Cranmer
    Mar 11, 2009
  2. Angus
    Replies:
    3
    Views:
    484
  3. Eduardo78
    Replies:
    0
    Views:
    258
    Eduardo78
    Nov 3, 2005
  4. Andrew Tomazos
    Replies:
    2
    Views:
    629
    Nobody
    Dec 12, 2011
  5. David
    Replies:
    5
    Views:
    92
    Michael Winter
    Nov 8, 2006
Loading...

Share This Page