【问题标题】:Subtracting 2 dimensional-arrays with a unique id column减去具有唯一 id 列的二维数组
【发布时间】:2017-06-06 12:24:33
【问题描述】:

我想减去两个二维数组,可选择将注意力放在“唯一 id”列上。

还想用更详细的描述方式来表达我在寻找什么。

但是,例如,给定两个数组:

big = [['foo','bar@','baz'],
       ['cat','moew@','purr'],
       ['dog','bark@','woof'],
       ['mew', 'two@', 'blue']]

little = [['foo','bar@','baz'],
          ['dog','moew@','woof'],
          ['dog','bark@','woof']]

然后我们可以减去它们:

big - little #=> [["cat", "moew@", "purr"], ["mew", "two@", "blue"]]

这很有效,因为['cat','moew@','purr'] != ['dog','moew@','woof']。但是,我希望这两个被认为是相等的,因为它们在“唯一 id”列中具有相同的值。

我就是这样解决的:

big = [['foo','bar@','baz'],
       ['cat','moew@','purr'],
       ['dog','bark@','woof'],
       ['mew', 'two@', 'blue']]

little = [['foo','bar@','baz'],
          ['dog','moew@','woof'],
          ['dog','bark@','woof']]


def subtract big, little, key_index=nil
  return big - little unless key_index
  little_keys = little.map { |row| row[key_index] }.flatten
  big.inject([]) do |result, row|
    result << row unless little_keys.grep(row[key_index]).any?
    result
  end
end

subtract(big,little) #=> [["cat", "moew@", "purr"], ["mew", "two@", "blue"]]
subtract(big, little, 1) #=> [["mew", "two@", "blue"]]

很想知道更多关于如何描述我正在尝试做的事情以及是否有更好的方法。

另外,我的方式是O(n^2),因为它要遍历整个数组两次吗?一次用于#inject,一次用于#grep

【问题讨论】:

    标签: arrays ruby algorithm enumerable


    【解决方案1】:
    big = [['foo','bar@','baz'],
           ['cat','moew@','purr'],
           ['dog','bark@','woof'],
           ['mew', 'two@', 'blue']]
    
    little = [['foo','bar@','baz'],
              ['foo','bark@','baz'],
              ['dog','moew@','woof'],
              ['dog','bark@','woof']]
    

    请注意,我已从问题中的示例更改了 little

    require 'set'
    
    little_set = little.each_with_object(Set.new) { |(_,u,_), set| set << u }
      #=> #<Set: {"bar@", "bark@", "moew@"}>
    
    big.reject { |_,m,_| little_set.include?(m) }
      #=> [["mew", "two@", "blue"]]
    

    【讨论】:

    • 不错。您的解决方案可能更快,因为它创建的对象更少。
    • 不过,您可以使用索引而不是硬编码数组结构。
    【解决方案2】:

    我在公共汽车上,无法轻松输入代码。如果您有唯一的 id,则可以将二维数组转换为以唯一 id 作为键、数组作为值的散列。

    big = { 'bar@' => ['foo','bar@','baz'], ... 
    

    你想要的数据应该是big.values_at(*(big.keys-little.keys))

    【讨论】:

    • 没有嵌套循环是不是更好用?
    • 是的,应该是 O(n) 而不是 O(n**2)
    • +1 谢谢@EricDuminil 今天晚些时候会投票。如果您有兴趣,请更新here :)
    • 顺便说一句,您想使用 each_with_object 而不是每次都注入并返回相同的对象。
    猜你喜欢
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 2011-05-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 2021-05-20
    • 1970-01-01
    相关资源
    最近更新 更多