Guest2
(Guest)
30 October 2008 21:14
1
Hi,
I have an array containing files names. How do I sort them so that I can
get the expected results?
Thanks,
Li
···
#############
files=[
"c:/ruby/self/2004/20.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/1.txt"
]
expected results:
[
"c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
]
"c:/ruby/self/2004/20.txt",
--
Posted via http://www.ruby-forum.com/ .
Li Chen wrote:
Hi,
I have an array containing files names. How do I sort them so that I can
get the expected results?
Thanks,
Li
#############
files=[
"c:/ruby/self/2004/20.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/1.txt"
]
expected results:
[
"c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
]
"c:/ruby/self/2004/20.txt",
You get that result because in "2" <=> "10" the comparison is byte by
byte and then "2" is > "1", so it aborts there with "2" being > than
"10".
What you want is called natural sorting. Googling for natsort and ruby
you should get a few results.
Regards
Stefan
···
--
Posted via http://www.ruby-forum.com/\ .
files = files.sort_by { |f| f[/\/(\d+)\.[^\/]*\Z/, 1].to_i }
There are several things to explain here:
- The #sort_by method calls the block on each element to produce a set of
surrogate values to use as sorting keys.
- The regular expression captures the series of digits between the last
slash in a string and the following dot.
- The method can be called on String in many ways, including passing a
RegExp and an index. That form returns the capture of the appropriate
index from matching the RegExp or nil if the RegExp does not match.
- Calling #to_i on the result means that it will either parse the captured
sequence of digits as an integer or, if the RegExp fails, return 0.
--Greg
···
On Fri, Oct 31, 2008 at 06:14:51AM +0900, Li Chen wrote:
Hi,
I have an array containing files names. How do I sort them so that I can
get the expected results?
Thanks,
Li
#############
files=[
"c:/ruby/self/2004/20.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/1.txt"
]
expected results:
[
"c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
]
"c:/ruby/self/2004/20.txt",
* Li Chen <chen_li3@yahoo.com> (22:14) schrieb:
files=[
"c:/ruby/self/2004/20.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/1.txt"
]
expected results:
[
"c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/20.txt",
]
files.sort_by { | fn | fn.match(/(\d+)\.txt$/)[1].to_i }
mfg, simon .... hth
botp1
(botp)
31 October 2008 04:01
5
apology in advance for dupl email. i sent an email an hrs back but it
seems it got blackholed
anyway, if you want basename numeric sorting, then just do
eg,
files.sort_by{|f| File.basename(f).to_i}
···
On Fri, Oct 31, 2008 at 5:14 AM, Li Chen <chen_li3@yahoo.com> wrote:
expected results:
[ "c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/20.txt",
]
Guest2
(Guest)
30 October 2008 21:43
6
here is my code:
C:\Users\Alex>irb
irb(main):001:0> files=[
irb(main):002:1* "c:/ruby/self/2004/20.txt",
irb(main):003:1* "c:/ruby/self/2004/3.txt",
irb(main):004:1* "c:/ruby/self/2004/2.txt",
irb(main):005:1* "c:/ruby/self/2004/10.txt",
irb(main):006:1* "c:/ruby/self/2004/1.txt"
irb(main):007:1> ]
=> ["c:/ruby/self/2004/20.txt", "c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt", "c:/ruby/self/
2004/10.txt", "c:/ruby/self/2004/1.txt"]
irb(main):008:0>
irb(main):009:0*
irb(main):010:0* files=files.sort_by do|s|
irb(main):011:1* s.split(/\//)[-1].split(/\./)[0].to_i
irb(main):012:1> end
=> ["c:/ruby/self/2004/1.txt", "c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt", "c:/ruby/self/2
004/10.txt", "c:/ruby/self/2004/20.txt"]
irb(main):013:0>
I am not sure if it is the Rubyish way.
Li
···
--
Posted via http://www.ruby-forum.com/ .
Since #to_i will stop at a non-digit, you could get simpler:
files.sort_by {|fn| fn[%r{.*/([^/]+)},1].to_i }
I tend to use %r{ } when the Regexp deals with / characters.
-Rob
Rob Biedenharn http://agileconsultingllc.com
Rob@AgileConsultingLLC.com
···
On Oct 30, 2008, at 6:34 PM, Simon Krahnke wrote:
* Li Chen <chen_li3@yahoo.com> (22:14) schrieb:
files=[
"c:/ruby/self/2004/20.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/1.txt"
]
expected results:
[
"c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/20.txt",
]
files.sort_by { | fn | fn.match(/(\d+)\.txt$/)[1].to_i }
mfg, simon .... hth
Robert_K1
(Robert K.)
31 October 2008 08:11
8
Very elegant! Here's another variant
irb(main):013:0> puts files.sort_by {|f| f[/\d+(?=\.txt$)/].to_i}
c:/ruby/self/2004/1.txt
c:/ruby/self/2004/2.txt
c:/ruby/self/2004/3.txt
c:/ruby/self/2004/10.txt
c:/ruby/self/2004/20.txt
=> nil
Kind regards
robert
···
2008/10/31 botp <botpena@gmail.com>:
On Fri, Oct 31, 2008 at 5:14 AM, Li Chen <chen_li3@yahoo.com> wrote:
expected results:
[ "c:/ruby/self/2004/1.txt",
"c:/ruby/self/2004/2.txt",
"c:/ruby/self/2004/3.txt",
"c:/ruby/self/2004/10.txt",
"c:/ruby/self/2004/20.txt",
]
apology in advance for dupl email. i sent an email an hrs back but it
seems it got blackholed
anyway, if you want basename numeric sorting, then just do
eg,
files.sort_by{|f| File.basename(f).to_i}
--
remember.guy do |as, often| as.you_can - without end
Robert_K1
(Robert K.)
31 October 2008 08:13
9
And here's a variant for cases where there are multiple subdirectories:
irb(main):010:0> puts files.sort_by {|f| f.scan(/\d+/).map{|x|x.to_i}}
c:/ruby/self/2004/1.txt
c:/ruby/self/2004/2.txt
c:/ruby/self/2004/3.txt
c:/ruby/self/2004/10.txt
c:/ruby/self/2004/20.txt
Kind regards
robert
···
--
remember.guy do |as, often| as.you_can - without end