在数组中排序数组&通过匹配元素删除

时间:2015-04-16 09:00:10

标签: ruby

我已经将excel解析为数组数组。新名称将添加到Excel的底部,其中一些可能已存在。所以我想首先对正在运行的数组进行排序。 然后,我想基于匹配前两个元素(以及第三个元素,如果它不为空)来删除任何重复项。保留的数组是没有第四个空元素的数组。

array  = []
sorted = []

array << ["John", "Smith", "null"] + [ "null", "null", "y", "y", "n", "n",   "n"]
array << ["Mary", "Jones","mary@addy.com,"  "fsgdseg", "comment", "y", "y", "n", "n", "n"]
array << ["Peter", "Ross", "null", "adfgehs", "comment", "y", "y", "n", "n", "n"]
array << ["John", "Smith", "john@smith.com", "dfsgfsdgsd", "comment", "y", "y", "n", "n", "n"]

array.sort_by {|e| [e[0], e[3]]} .each {|line| sorted << line }

sorted.each{ |i| p i}

#=> ["John", "Smith", "john@smith.com", "dfsgfsdgsd", "comment", "y", "y", "n", "n", "n"]
#=> ["John", "Smith", "null", "null", "null", "y", "y", "n", "n", "n"]
#=> ["Mary", "Jones", "mary@addy.com,fsgdseg", "comment", "y", "y", "n", "n", "n"]
#=> ["Peter", "Ross", "null", "adfgehs", "comment", "y", "y", "n", "n", "n"]

现在我想删除元素0,1匹配的数组。 2(如果有)&amp;删除元素3不为空的那个。

2 个答案:

答案 0 :(得分:4)

解释问题

我认为问题如下。数组(数组的元素)将被分组。如果每个数组的前三个元素相同或前两个元素相同且第三个元素等于&#34; null&#34;则两个数组在同一组中。对于一个或两个阵列。如果一个组由一个数组组成,则该组将被该数组替换。如果一个组包含两个或多个数组,则其中一个数组中的第四个元素将不会是&#34; null&#34;,并且该组将被该数组替换..

如果这种解释不正确,那么修改下面的代码以符合正确的解释应该不难。

<强>代码

def select_arrays(array)
  h = array.group_by { |a| a[0,3] }
  keys = h.keys
  h.each_key do |k|
    next unless k[2]=="null"
    key = keys.find { |kk| (k!=kk) &&  k[0,2]==kk[0,2] }
    h[key].concat(h.delete(k)) if key
  end.values.map { |a|
     (a.size==1) ? a.first : a.find { |e| e[3] != "null"} }.sort
end

示例

array = [
  ["John", "Smith", "null", "null", "null", "y", "y", "n", "n", "n"],
  ["Peter", "Ross", "null", "adfgehs", "comment", "y", "y", "n", "n", "n"],
  ["Mary", "Jones", "mary@addy.com", "fsgdseg", "comment", "y", "y", "n", "n", "n"],
  ["John", "Smith", "john@smith.com", "dfsgfsdgsd", "comment", "y", "y", "n", "n", "n"],
  ["Peter", "Ross", "Bubba", "null", "comment", "y", "y", "n", "n", "n"],
  ["John", "Smith", "john@smith.com", "null", "comment", "y", "y", "n", "n", "n"]
]

select_arrays(array)
  #=> [["John", "Smith", "john@smith.com", "dfsgfsdgsd",
  #       "comment", "y", "y", "n", "n", "n"],
  #    ["Mary", "Jones", "mary@addy.com", "fsgdseg",
  #      "comment", "y", "y", "n", "n", "n"],
  #    ["Peter", "Ross", "null", "adfgehs",
  #       "comment", "y", "y", "n", "n", "n"]] 

<强>解释

步骤如下:

  • 使用Enumerable#group_by按前三个元素对数组进行分组,产生一个哈希,键是三个元素数组,值是一个数组,其前三个元素与键匹配。
  • 对于第三个元素为&#34; null&#34;的每个键,查看是否存在与前两个​​元素匹配的另一个键。如果存在,则将找到的键的值与第一个键的值连接,并删除第一个键的键值对。这会将散列减少为没有前两个元素相同的键对。
  • 将哈希值中的值提取到数组的x数组中。
  • x(数组)的每个元素转换为单个数组。如果元素y只有一个元素,请转换为y.first;否则选择arr的{​​{1}}元素y
  • 如果需要,请对生成的数组进行排序。

对于上面的arr[2] != "null",我们计算:

array

枚举器的每个元素都由Hash#each传递给块,并分配给块变量h = array.group_by { |a| a[0,3] } #=> {["John", "Smith", "null"]=> # [["John", "Smith", "null", "null", # "null", "y", "y", "n", "n", "n"]], # ["Peter", "Ross", "null"]=> # [["Peter", "Ross", "null", "adfgehs", # "comment", "y", "y", "n", "n", "n"]], # ["Mary", "Jones", "mary@addy.com"]=> # [["Mary", "Jones", "mary@addy.com", "fsgdseg", # "comment", "y", "y", "n", "n", "n"]], # ["John", "Smith", "john@smith.com"]=> # [["John", "Smith", "john@smith.com", "dfsgfsdgsd", # "comment", "y", "y", "n", "n", "n"], # ["John", "Smith", "john@smith.com", "null", # "comment", "y", "y", "n", "n", "n"]], # ["Peter", "Ross", "Bubba"]=> # [["Peter", "Ross", "Bubba", "null", # "comment", "y", "y", "n", "n", "n"]]} keys = h.keys #=> [["John", "Smith", "null"], # ["Peter", "Ross", "null"], # ["Mary", "Jones", "mary@addy.com"], # ["John", "Smith", "john@smith.com"], # ["Peter", "Ross", "Bubba"]] enum = h.each_key #=> #<Enumerator: {["John", "Smith", "null"]=>[["John", "Smith",... # ...}:each_key> 。我们可以使用Enumerator#next

来模拟这一点
k

作为k = enum.next #=> ["John", "Smith", "null"] next unless k[2]=="null" ,我们不会走到循环的末尾。

k[2] == "null"

我们找到了与前两个元素匹配的其他键,因此我们将key = keys.find { |kk| (k!=kk) && k[0,2]==kk[0,2] } #=> ["John", "Smith", "john@smith.com"] 添加到h[k]并删除键h[key]

k

我们确认已删除一个密钥:

h[key].concat(h.delete(k)) if key
  #=> [["John", "Smith", "john@smith.com", "dfsgfsdgsd",
  #       "comment", "y", "y", "n", "n", "n"],
  #    ["John", "Smith", "john@smith.com", "null",
  #       "comment", "y", "y", "n", "n", "n"],
  #    ["John", "Smith", "null", "null",
  #        "null", "y", "y", "n", "n", "n"]] 

现在将h.each_key.to_a #=> [["Peter", "Ross", "null"], # ["Mary", "Jones", "mary@addy.com"], # ["John", "Smith", "john@smith.com"], # ["Peter", "Ross", "Bubba"]] 的下一个元素传递到块中:

enum

现在:

k = enum.next
  #=> ["Peter", "Ross", "null"] 
next unless k[2]=="null"
key = keys.find { |kk| (k!=kk) &&  k[0,2]==kk[0,2] }
  #=> ["Peter", "Ross", "Bubba"] 
h[key].concat(h.delete(k)) if key

我们处理h #=> {["Mary", "Jones", "mary@addy.com"]=> # [["Mary", "Jones", "mary@addy.com", "fsgdseg", # "comment", "y", "y", "n", "n", "n"]], # ["John", "Smith", "john@smith.com"]=> # [["John", "Smith", "john@smith.com", "dfsgfsdgsd", # "comment", "y", "y", "n", "n", "n"], # ["John", "Smith", "john@smith.com", "null", # "comment", "y", "y", "n", "n", "n"], # ["John", "Smith", "null", "null", # "null", "y", "y", "n", "n", "n"]], # ["Peter", "Ross", "Bubba"]=> # [["Peter", "Ross", "Bubba", "null", # "comment", "y", "y", "n", "n", "n"], # ["Peter", "Ross", "null", "adfgehs", # "comment", "y", "y", "n", "n", "n"]]} 的其他元素时不再对h进行更改,因为enum代表所有这些值。

现在提取k[2] != "null"

的值
h

现在浏览一下这些值。如果值包含单个元素,则用该元素替换该数组; else用v = h.values #=> [[["Mary", "Jones", "mary@addy.com", "fsgdseg", # "comment", "y", "y", "n", "n", "n"]], # [["John", "Smith", "john@smith.com", "dfsgfsdgsd", # "comment", "y", "y", "n", "n", "n"], # ["John", "Smith", "john@smith.com", "null", # "comment", "y", "y", "n", "n", "n"], # ["John", "Smith", "null", "null", # "null", "y", "y", "n", "n", "n"]], # [["Peter", "Ross", "Bubba", "null", # "comment", "y", "y", "n", "n", "n"], # ["Peter", "Ross", "null", "adfgehs", # "comment", "y", "y", "n", "n", "n"]]]

元素a替换数组
a[3] != "null"

最后,如果需要,排序:

arr = v.map { |a| (a.size==1) ? a.first : a.find { |e| e[3] != "null"} }
  #=> [["Mary", "Jones", "mary@addy.com", "fsgdseg",
  #       "comment", "y", "y", "n", "n", "n"],
  #    ["John", "Smith", "john@smith.com", "dfsgfsdgsd",
  #       "comment", "y", "y", "n", "n", "n"],
  #    ["Peter", "Ross", "null", "adfgehs",
  #       "comment", "y", "y", "n", "n", "n"]] 

产生上面例子中显示的结果。

答案 1 :(得分:2)

也许我不明白这个问题,但也许这就是你想要的。

所以也许这个?

array, sorted = [], []

array << ["John", "Smith", "null"] + [ "null", "null", "y", "y", "n", "n",   "n"]
array << ["Mary", "Jones","mary@addy.com,"  "fsgdseg", "comment", "y", "y", "n", "n", "n"]
array << ["Peter", "Ross", "null", "adfgehs", "comment", "y", "y", "n", "n", "n"]
array << ["John", "Smith", "john@smith.com", "dfsgfsdgsd", "comment", "y", "y", "n", "n", "n"]

is_define = {}
array.sort_by {|e| [e[0], e[3]]} .each {|line|
  unless line[3].to_s == "null"
    full_name_a = line[0..1]

    if is_define.has_key?(full_name_a)
      unless is_define[full_name_a].include?(line[3])
        is_define[full_name_a] << line[3]
        sorted << line
      end
    else
      is_define[full_name_a] = [line[3]]
      sorted << line
    end
  end
}
sorted.each do |a| p a end

# => ["John", "Smith", "john@smith.com", "dfsgfsdgsd", "comment", "y", "y", "n", "n", "n"]
# => ["Mary", "Jones", "mary@addy.com,fsgdseg", "comment", "y", "y", "n", "n", "n"]
# => ["Peter", "Ross", "null", "adfgehs", "comment", "y", "y", "n", "n", "n"]

我有结果,所以我更新了源代码。