Извлекать дубликаты записей из CSV на основе выбранных заголовков - PullRequest
0 голосов
/ 23 августа 2011

У меня есть CSV-файл с несколькими тысячами деталей клиента.Я хотел бы извлечь дублированных клиентов на основе одинаковых значений для выбранных заголовков.

Например, я хотел бы извлечь всех клиентов, если существует более одной записи с одинаковыми «фамилией» и «почтовым индексом».

"surname","postcode","other-stuff-that-doesn't-matter"...
"smith",  "AB1 2CD", "dxfh"...
"smith",  "AB1 2CD", "98sf"...
"jones",  "BC2 3DE", "as0j"...
"jones",  "BC2 3DE", "9as6"...
"blogs",  "BC2 3DE", "9as6"...

Исходя из вышеизложенного, программа выдаст новый CSV, например, так:

"surname","postcode","other-stuff-that-doesn't-matter"...
"smith",  "AB1 2CD", "dxfh"...
"smith",  "AB1 2CD", "98sf"...
"jones",  "BC2 3DE", "as0j"...
"jones",  "BC2 3DE", "9as6"...

EDIT

Спасибо за помощь.Я думаю, что у меня есть рабочее решение, но мне интересно знать, можно ли его оптимизировать (я уверен, что это возможно!).

set_one    = Set.new
set_two    = Set.new
duplicates = Array.new
headers    = nil

CSV.foreach('customers.csv', :headers => true, :header_converters => :symbol) do |row|
  headers = row.headers unless headers
  values = [row[:surname], row[:post_code]]
  if set_one.include? values
    set_two << values
  else
    set_one << values 
  end
end

CSV.foreach('customers.csv', :headers => true, :header_converters => :symbol) do |row|
  values = [row[:surname], row[:post_code]]
  if set_two.include? values
    duplicates << row
  end
end

CSV.open("duplicate-customers.csv", "wb") do |csv|
  csv << headers
  duplicates.each { |dupe| csv << dupe }
end

1 Ответ

3 голосов
/ 23 августа 2011

Давайте сначала прочитаем в csv (не обрабатывает экранирование или кавычки, просто пример)

csv = []
columns = []
File.read('csv.file') do |row|
  if csv.empty?
    columns=row.split(',')
  else
    row_data={}
    row.split(',').each_with_index do |c,i|
      row_data[columns[i]] = c
    end
    csv << row_data
  end
end

Хорошо, что мы будем делать с данными?Это выглядит так:

[{'surname' => 'smith', 'postcode' => '1234', 'otherstuff' => 'xyz' },
 {'surname' => 'jones', 'postcode' => '1234', 'otherstuff' => 'xyz' },
 {'surname' => 'smith', 'postcode' => '2345', 'otherstuff' => 'xyz' },
 {'surname' => 'smith', 'postcode' => '1234', 'otherstuff' => 'xyz' }]

Как насчет чего-то вроде:

csv.select do |c| 
  csv.any? do |s| 
    s['surname'].eql?(c['surname']) && s['postcode'].eql?(c['postcode']) 
  end
end

Хорошо, это медленно и не умно.Давайте перейдем к решению 2, сгенерируем хеш-ключ из данных, которые мы хотим проверить на уникальность:

sneakyhash={}
csv.each do |row|
  magic_string = [row['surname'], row['postcode']].join("--MaGiCaL--SpLiTTinG--StRiNG--")
  if sneakyhash[magic_string].nil?
    sneakyhash[magic_string] = 1
  else
    puts "this guy looks suspicious: " + row.join(,)
  end
end

Далеко от оптимального, но просто обдумать вслух.Если это «одноразовая» вещь, и вам просто нужно проанализировать файл, перейдите к тому, что вы можете придумать.

Что вы, вероятно, захотите сделать, - это сохранить эту идентифицирующую строку в массиве или хэше во время чтения CSV-файла и посмотреть, соответствует ли текущая строка какой-либо из сохраненных уникальных строк и что-то сделать, если это произойдет.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...