使用唯一 id 列减去 2 维数组

Subtracting 2 dimensional-arrays with a unique id column

我想减去两个二维数组,可以选择将注意力放在 "unique 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']。但是,我希望这两个被认为是相等的,因为它们在 "unique 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?

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

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

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

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