识别特定CSV输出中的重复项

时间:2014-03-26 01:13:53

标签: ruby arrays parsing csv

Ruby新手在这里。我有一个产品csv,其中第一个col是唯一的SKU,第二个col是可以在多个产品中复制的产品ID(+许多其他cols,但这些是相关的)。像:

SKU     | Prod ID
 99     | 10384
100     | 10385
101     | 10385
102     | 10386
103     | 10386
104     | 10387

在我写的脚本中,第一次使用产品ID将成为“父”,产品ID的任何后续实例都会得到不同的处理(即不同的大小)。

目前正在阅读整个CSV而不是做foreach行,因为我认为我需要所有可用的数据来查找重复项。

问题是我不确定如何在第一次使用产品ID时识别,然后识别其使用的任何其他实例。

我的第一个想法是以某种方式识别重复项(uniq?),然后创建一个新列,如果它是第一次发生则放1,如果先前发生则放0。看完uniq之后,我不知道如何回到主列表并标记我的1和0。

有人可以指出我需要看的课程/方法的方向吗?

谢谢, 利安

为John D编辑:这给了我哈希,但是以1:1格式而不是1:所有prod ID实例

CSV.foreach(INPUT, :headers => true , :header_converters => :symbol, :col_sep => "|",     :quote_char => "\x00") do |csv_obj|
  items[csv_obj.fields[0]] = [csv_obj.fields[1]]
end

所以给出; “230709”=> [“88507”],“109064”=> [“9019”]

2 个答案:

答案 0 :(得分:2)

您认为Sku是唯一标识符,实际上它可能是唯一标识符。但是,如果您转过头来考虑ProductID作为唯一标识符,那么您可以构建一个Hash,其中键是ProductID,值为Array Sku。然后,您就可以跟踪哪些Sku与哪个ProductID相关联。

当然,您将以其他方式阅读此内容,但最终结果将类似于:

products = 
{
  10384 => [99],
  10385 => [100, 101],
  10386 => [102, 103],
  10387 => [104]
}

以下是如何构建此Hash的示例:

#!/usr/bin/env ruby
require 'csv'

source = [
  "99|110384",
  "100|10385",
  "101|10385",
  "102|10386",
  "103|10386",
  "104|10387"
].join("\n")

source = CSV.parse(source, :col_sep => "|")

hh = source.inject({}) do |memo, row|
  sku = row[0]
  prod = row[1]

  memo[prod] = [] unless memo.include?(prod) 
  memo[prod] << sku
  memo
end

puts hh

答案 1 :(得分:1)

.group_by()相对较新(虽然它在Rails中有一个较旧的版本),但非常方便,应该完成你的大部分繁重工作。

如果您创建一个类来保存每一行并将它们放在Array中,那么您可以使用仅检查每个对象的产品ID字段的块来调用group_by方法。

这会为您提供Hash,您可以使用.keys.each进行迭代。

假设有很多关于你的程序的东西,希望是半明显的,比如:

transactionHash = transactions.group_by { |x| x.productId }

然后,您可以通过以下方式浏览每个产品的交易清单:

transactionHash.each do |prodId,transList|
  # transList has all of your transaction objects per product
end

同样,这假设您将交易保留在对象列表中。例如,如果您将每个事务存储在数组中,x.productId将类似于x[1]