开发者

How to deduplicate an array with substring variations where one substring has precedence over another?

I have a dataset similar to this: http://pastie.org/private/3u1reg72nnjfsgqzgqzwra

开发者_如何学JAVAThe list is a set of filenames that need to be processed. When a filename that has a substring of 10u exists along with one with a substring of 2u, the filename with 10u in it has a subset of data from the file with the 2u substring. In other words, when you have something like:

20021203_V9ut_2u.txt 
20021203_V9ut_10u.txt 
    or 
V9cd_2u.txt
V9cd_10u.txt

the 20021203_V9ut_10u.txt and V9cd_10u.txt should be removed from the list and only the filenames with 1u should remain in the list.

I've attempted a few various methods, but they all feel too much like C or hackish. I have also thought about splitting the string and then building a hash with the values of the 1u or 10u and then if a key with a 10u value in it exists, replace it with 1u, else discard and then remap the hash to an array for processing the file contents.

What is the "best" or most ruby way to do this and can you provide an example?


If your file list sometimes contains files that don't have a perfect match of 2u and 10u this will help you. It removes the 10u files, if and only if there is a corresponding 2u file, leaves it in the resulting list otherwise.

files = %w(20021203_V9ut_2u.txt 
20021203_V9ut_10u.txt 
V9cd_2u.txt
V9cd_10u.txt
test1_2u.txt
thing2_10u.txt)

# Reverse sort them if they aren't already that way

files = files.sort {|a,b| b <=> a }

puts files.inspect

scrubbed_files = []
files.each_with_index { |f,i| 
  scrubbed_files << f unless f =~ /(.*)_10u\.(.*)/ && files[i-1] =~ /#{$1}_2u\.#{$2}/
}

puts scrubbed_files.inspect


Assuming you have an array of all_filenames as strings:

filenames_2u = all_filenames.reject!{ |f| f =~ /10u/ } # edited to be actual working ruby

edit If the file you provided is what you're working with:

all_filenames = IO.readlines('filenames.txt')


This way is more fun:

a.map {|x| x.split(/_/)}.group_by {|x| x[0...-1]}.map {|_,xx| xx.sort_by {|x| x.last.to_i}.first.join("_")}

That is, split the names into arrays at the underscores, group these by the stems (the parts up to the last underscore), then for each group sort the names by the integer versions of the last bit and take the first one.

This will work for any Xu numbering scheme, so if you had 2u and 5u and 10u you'd get the 2u version, and if you had 10u and 20u you'd get the 10u.

group_by is cool.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜