2015-01-07 39 views
0

我有兩個csv文件,每個文件有13列。如何使用保存數據的規則將兩個CSV與幾乎相同的數據集合並? (使用Ruby&FasterCSV)

每行的第一列包含一個唯一的字符串。有些複製在每個文件中,有些僅存在於一個文件中。

如果該行只存在於一個文件中,我想將它保留在新文件中。

如果它存在於兩者中,我想在同一行的某一列中保留具有某個值(或缺少某個值)的值。

例如:

文件1:

D600-DS-1991, name1, address1, date1 
D601-DS-1991, name2, address2, date2 
D601-DS-1992, name3, address3, date3 

文件2:

D600-DS-1991, name1, address1, time1 
D601-DS-1992, dave1, address2, date2 

我會繼續的第一個文件的第一行,因爲第四列包含date代替time 。 我會保留自第一列以來第一個文件的第二行,第一行值是唯一的。 我會將第二個文件的第二行作爲新文件的第三行,因爲它包含第二列中「name#」以外的文本。

我是否應該先將所有唯一值映射到另一個值,以便每個文件包含相同數量的條目 - 即使有些條目是空白的或僅具有填充數據?

我只知道一點ruby和python ......但我更喜歡用一個單獨的Ruby文件解決這個問題,因爲我可以更好地理解代碼。如果您無法在Ruby中完成,請隨時以不同的方式回答!

+0

你到目前爲止試過了什麼?就目前而言,這只是要求有人爲你做骯髒的工作。 –

+0

第一個文件是否總是乾淨或是否包含可能過時的行?如果是這樣,如果兩個文件在第四列中都有'time'作爲特定ID,會發生什麼? –

+0

@Anthony我認爲與「一些在每個文件中重複」他意味着一個條目可以出現在這兩個文件中。 –

回答

0

我不是我的解決方案超級高興,但它的工作原理:

require 'csv' 

def readcsv(filename) 
    csv = {} 
    CSV.foreach(filename) do |line| 
    csv[line[0]] = { name: line[1], address: line[2], date: line[3] } 
    end 
    csv 
end 

csv1 = readcsv('orders1.csv') 
csv2 = readcsv('orders2.csv') 

results = {} 
csv1.each do |id, val| 
    unless csv2[id] 
    results[id] = val # checks to see if it only exists in 1 file 
    next 
    end 

    #see if name exists 
    if (val[:name] =~ /name/) && (csv2[id]) && (csv2[id][:name] =~ /name/).nil? 
    csv1.delete(id) 
    end 

    #missing some if statement regarding date vs. time 
end 

results = results.merge(csv2) # merge together whatever is remaining 

CSV.open('newfile.csv', 'w') do |csv| 
    results.each do |key, val| 
    row = [] 
    csv << (row.push(key, val.values)).flatten 
    end 
end 

newfile.csv的輸出:

D601-DS-1991, name2, address2, date2 
D600-DS-1991, name1, address1, time1 
D601-DS-1992, dave1, address2, date2 
0

我不會給你完整的代碼,但這裏有一個通用的方法來這樣一個問題:

require 'csv' 

# list of csv files to read 
files = ['a.csv', 'b.csv'] 

# used to resolve conflicts when we have a existing entry with same id 
# here, we prefer the new entry if its fourth column starts with `'date'` 
# this also means that the last file in the list above wins if both entries are valid. 
def resolve_conflict(existing_entry, new_entry) 
    if new_entry[3].start_with? 'date' 
    new_entry 
    else 
    existing_entry 
    end 
end 

# keep a hash of entries, with the unique id as key. 
# we use this id to detect duplicate entries later on. 
entries = {} 

CSV.foreach(file) do |new_entry| 
    # get id (first column) from row 
    id = new_entry[0] 

    # see if we have a conflicting entry 
    existing_entry = entries[id] 
    if existing_entry.nil? 
    # no conflict, just save the row 
    entries[id] = new_entry 
    else 
    # resolve conflict and save that 
    entries[id] = resolve_conflict(existing_entry, new_entry) 
    end 
end 

# now all conflicts are resolved 
# note that stale rows from the first file could now be in the result 
# you might want to filter them out as well 
# we can now build a new csv file with the result 
CSV.open("result.csv", "w") do |csv| 
    entries.values.each do |row| 
    csv << row 
    end 
end 
相關問題