sort array by some text

M

Ma Fe

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
 
T

Todd Benson

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

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
 
M

Ma Fe

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...
 
T

Todd Benson

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
 
R

Robert Klemme

2008/3/12 said:
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

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
 
R

Rodrigo Bermejo

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.
 
R

Robert Klemme

2008/3/12 said:
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.

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"]

;-)

Kind regards

robert
 
7

7stud --

Ma said:
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"]
 
W

William James

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"]


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[-4,4] == '.txt'
a[0],a = a,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, -4 ) == '.txt' then
a[1],a = a,a[1]
end
end
end

print( os.clock() - when )

--output--
0.968
 
P

Paul Mckibbin

Ma said:
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
 
R

Rodrigo Bermejo

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.
 
T

Todd Benson

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"]

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
 
T

Todd Benson

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"]

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

I reply to myself too often on this board. That won't work either,
because it won't preserve the array contents.

Todd
 
T

Todd Benson

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"
 

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

No members online now.

Forum statistics

Threads
474,285
Messages
2,571,416
Members
48,107
Latest member
AmeliaAmad

Latest Threads

Top