move to front of array

P

Payton Swick

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
 
F

Florian Frank

Payton said:
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 })
 
J

Jacob Fugal

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
 
L

Logan Capaldo

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 ) )
 
E

Eero Saynatkari

Payton said:
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))


E
 
D

Dan Diebolt

--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--
 
E

Ezra Zygmuntowicz

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
 
J

Jacob Fugal

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
 
D

Daniel Berger

Jacob said:
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
 
D

Dan Diebolt

--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--
 
J

Jacob Fugal

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
 
D

Devin Mullins

Payton said:
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.
 
S

Simon Kröger

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
 
D

Dan Diebolt

--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--
 
P

Payton Swick

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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,570
Members
45,045
Latest member
DRCM

Latest Threads

Top