Sort array by some text

Hi, i have array with file names
a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’]
how can i sort it that always first value will be *.txt file ?

Thanks, fryt

well I dont know where in array i have .txt files but its sure that
there is just one and i want to put it at first place of array…

On Wed, Mar 12, 2008 at 12:02 AM, Ma Fe [email protected] wrote:

Hi, i have array with file names
a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’]
how can i sort it that always first value will be *.txt file ?

Thanks, fryt

Posted via http://www.ruby-forum.com/.

a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’]
#assume you want reverse sort?
a.sort_by {|i| i.scan /..*?$/}.reverse

You understand, of course, this won’t give you .txt as a first hit if
you have a .zip. It simply reverse sorts by the letters following a
dot.

If you just want .txt files, maybe use #select instead…

a.select {|i| i =~ /..txt$/}

Or you could use #partition if you don’t care about the order of other
attributes, but want to hold on to the entire array…

a.partition {|i| i =~ /..txt$/}.flatten

Todd

On Wed, Mar 12, 2008 at 12:34 AM, Ma Fe [email protected] wrote:

well I dont know where in array i have .txt files but its sure that
there is just one and i want to put it at first place of array…

Try using the #partition method (my last example) then. It gives you
all .txt files at the beginning of the array. I made a mistake
though. There should only be one dot, not two for that (same thing if
you use #select)…

a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’, ‘four.txt’]
a_new = a.partition {|i| i =~ /.txt$/}
p a_new

Todd

2008/3/12, Todd B. [email protected]:

a_new = a.partition {|i| i =~ /.txt$/}
p a_new

For the fun of it: here’s a solution with #inject:

irb(main):009:0> a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’]
=> [“one.jpg”, “two.txt”, “three.pdf”]
irb(main):010:0> a.inject([[],[]]) {|(tx,ot),x| (/.txt$/ =~ x ? tx :
ot) << x;[tx,ot]}.flatten
=> [“two.txt”, “one.jpg”, “three.pdf”]

There’s even a version with two #injects:

irb(main):011:0> a.inject([[],[]]) {|(tx,ot),x| (/.txt$/ =~ x ? tx :
ot) << x;[tx,ot]}.inject {|a,b| a.concat b}
=> [“two.txt”, “one.jpg”, “three.pdf”]

It’s been a while so I had to do it. Once in a while I need my
#injection. :-))

Kind regards

robert

2008/3/12, Rodrigo B. [email protected]:

→ [“a.txt”, “two.txt”, “one.jpg”, “three.pdf”, “a.az”, “a.z”]

the sort_by block can be improved surely.

Here’s one way: sorting with priorities:

irb(main):006:0> a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’,‘a.txt’, ‘a.az’
, ‘a.z’]
=> [“one.jpg”, “two.txt”, “three.pdf”, “a.txt”, “a.az”, “a.z”]
irb(main):007:0> a.sort_by {|s| [/.txt$/=~s ? 0 : 1, s]}
=> [“a.txt”, “two.txt”, “a.az”, “a.z”, “one.jpg”, “three.pdf”]

:wink:

Kind regards

robert

Ma Fe wrote:

well I dont know where in array i have .txt files but its sure that
there is just one and i want to put it at first place of array…

a.select {|i| i =~ /…txt$/}

That doesn’t work.

b = a.partition {|i| i =~ /.txt$/}

Neither does that.

This is faster than all the solutions posted so far:

a = [‘one.jpg’, ‘two.kzv’, ‘a.txt’, ‘a.az’]
new_a = [1]

for elmt in a
if elmt[-3] == ?t
new_a[0] = elmt
else
new_a << elmt
end
end

–output:–
[“a.txt”, “one.jpg”, “two.kzv”, “a.az”]

a = [‘one.jpg’, ‘two.txt’, ‘three.pdf’,‘a.txt’, ‘a.az’ , ‘a.z’]
a_new=a.sort_by do |x|
if x =~ /.txt$/
0
else
1
end
end
p a_new
–> [“a.txt”, “two.txt”, “one.jpg”, “three.pdf”, “a.az”, “a.z”]

the sort_by block can be improved surely.

Ma Fe wrote:

well I dont know where in array i have .txt files but its sure that
there is just one and i want to put it at first place of array…

Do you want to sort the array, or just make sure that element is the
first one? If the former case, and speed is an issue, you can just swap
the first element with it which should reduce time of execution. Of
course, I have no empirical evidence of this, but thought that this
question might reduce if that is the case.

Mac

On Mar 12, 1:56 pm, 7stud – [email protected] wrote:

Ma Fe wrote:

well I dont know where in array i have .txt files but its sure that
there is just one and i want to put it at first place of array…

end
end

–output:–
[“a.txt”, “one.jpg”, “two.kzv”, “a.az”]

Iters = 99_000
a, new_a = nil

t = Time.now
Iters.times{
a = %w(one.jpg two.kzv a.az b.mp3 c.png a.txt d.tif e.gif f.mp4
g.pdf)
new_a = [1]
for elmt in a
if elmt[-4,4] == ‘.txt’
new_a[0] = elmt
else
new_a << elmt
end
end
}
p Time.now - t

t = Time.now
Iters.times{
a = %w(one.jpg two.kzv a.az b.mp3 c.png a.txt d.tif e.gif f.mp4
g.pdf)
1.upto(a.size-1){|i|
if a[i][-4,4] == ‘.txt’
a[0],a[i] = a[i],a[0]
break
end
}
}
p Time.now - t

–output–
4.422
3.359

Lua:

when = os.clock()

for _ = 1,99000 do
a = {‘one.jpg’,‘two.uzv’,‘a.az’,‘b.mp3’,‘c.png’,‘a.txt’,
‘d.tif’,‘e.gif’,‘f.mp4’,‘g.pdf’}
for i = 2, #a do
if string.sub( a[i], -4 ) == ‘.txt’ then
a[1],a[i] = a[i],a[1]
end
end
end

print( os.clock() - when )

–output–
0.968

I’ve seen many post lately, where seems the best solution is the faster
one.

but remember, optimize until you need it…programmer time vs. cpu
time…maintenance.

Use ruby, if there is a speed need that ruby does not cover, you already
have a prototype to build a faster implementation.

the turtle vs. rabbit fable.

there’s always an open door.
faster=C_Program

-r.

On Wed, Mar 12, 2008 at 1:56 PM, 7stud – [email protected]
wrote:

Neither does that.

Yes, I said all this in the next post.

Todd

On Wed, Mar 12, 2008 at 6:13 PM, Todd B. [email protected]
wrote:

if elmt[-3] == ?t
one text file.
puts a
I reply to myself too often on this board. That won’t work either,
because it won’t preserve the array contents.

Todd

On Wed, Mar 12, 2008 at 1:56 PM, 7stud – [email protected]
wrote:

new_a << elmt

end
end

–output:–
[“a.txt”, “one.jpg”, “two.kzv”, “a.az”]

Fast and somewhat of an eyesore. Doesn’t work if there’s more than
one text file.

About the same speed and more rubyish…

a = [‘one.jpg’, ‘two.kzv’, ‘a.txt’, ‘a.az’]
t = Time.now
new_a = []
for elmt in a
(a.unshift elmt && a.pop) if elmt[-3] == ?t
end
puts a

cheers,
Todd

Todd B. wrote:

On Wed, Mar 12, 2008 at 1:56 PM, 7stud – [email protected]
wrote:

new_a << elmt

end
end

–output:–
[“a.txt”, “one.jpg”, “two.kzv”, “a.az”]

Fast and somewhat of an eyesore. Doesn’t work if there’s more than
one text file.

And since there isn’t…

On Wed, Mar 12, 2008 at 6:13 PM, Todd B. [email protected]
wrote:

a = [‘one.jpg’, ‘two.kzv’, ‘a.txt’, ‘a.az’]
new_a = []
for elmt in a
(a.unshift elmt && a.pop) if elmt[-3] == ?t
change this ^^^^^^ line to “a.unshift a.delete(elem) if elmt[-3] == ?t”

On Wed, Mar 12, 2008 at 6:27 PM, 7stud – [email protected]
wrote:

And since there isn’t…

Okay … works to spec.

On Wed, Mar 12, 2008 at 6:50 PM, Todd B. [email protected]
wrote:

Okay … works to spec.

No it doesn’t, what if you tap on a “something.tgz” file on the end of
the array. William had the right idea.

Todd