现有两个 CSV 输入文件,我们希望创建一个 CSV 输出文件:
FNAME1 = 'file1.csv'
FNAME2 = 'file2.csv'
FILE_OUT = 'output.csv'
让我们首先创建两个输入文件。
File.write(FNAME1, "username;userid;full_name;follower_count;following_count;media_count;email;category\nhelloworld;1234;data3;data4;data5;data6;data7;data8\n")
#=> 136
File.write(FNAME2, "username;owner_id;owner_profile_pic_url;media_url;tagged_brand_username\nhelloworld;1234;data3b;data4b;data5b\n")
#=> 109
现在执行读取这些文件、操作其内容并写入输出文件的步骤。
require 'csv'
首先读取两个输入文件并将其内容保存在变量中。
def read_csv(fname)
CSV.read(fname, col_sep: ';', headers: true)
end
csv1 = read_csv(FNAME1)
#=> #<CSV::Table mode:col_or_row row_count:2>
csv2 = read_csv(FNAME2)
#=> #<CSV::Table mode:col_or_row row_count:2>
注意:
csv1.to_a
#=> [["username", "userid", "full_name", "follower_count", "following_count",
# "media_count", "email", "category"],
# ["helloworld", "1234", "data3", "data4", "data5",
# "data6", "data7", "data8"]]
csv2.to_a
#=> [["username", "owner_id", "owner_profile_pic_url", "media_url", "tagged_brand_username"],
# ["helloworld", "1234", "data3b", "data4b", "data5b"]]
如您所见,这些是普通数组,所以如果我们希望此时可以忘记它们来自 CSV 文件并使用标准 Ruby 方法来创建所需的输出文件。
现在查看"username" 的值在两个文件中是否相同:
username1 = csv1['username'].first
#=> "helloworld"
username2 = csv2['username'].first
#=> "helloworld"
csv1['username'] 在"helloworld" 列中创建一个包含所有值的数组。这里就是["helloworld"];因此.first。当然,csv2 也是如此。
如果username1 == username2 #=> false 我们执行了我不清楚的操作,则退出。从今以后,我假设这两个用户名是相等的。
将两个文件的标题读入数组。
headers1 = csv1.headers
#=> ["username", "userid", "full_name", "follower_count", "following_count",
# "media_count", "email", "category"]
headers2 = csv2.headers
#=> ["username", "owner_id", "owner_profile_pic_url", "media_url",
# "tagged_brand_username"]
输出文件将包含headers1中的所有列和headers2中的所有列,除了headers2中的"username"和"owner_id",所以接下来让我们去掉@中的那些标题987654342@:
headers2 -= ["username", "owner_id"]
#=> ["owner_profile_pic_url", "media_url", "tagged_brand_username"]
接下来检索第一个文件中标题的值:
values1 = headers1.flat_map { |h| csv1[h] }
#=> ["helloworld", "1234", "data3", "data4", "data5", "data6", "data7", "data8"]
以及第二个文件中剩余标头的值:
values2 = headers2.flat_map { |h| csv2[h] }
#=> ["data3b", "data4b", "data5b"]
我们将修改下面的values2,所以我们需要保存它的当前大小:
values2_size = values2.size
#=> i
输出文件中标题行之后的第一行是包含值:
values1 += values2
#=> ["helloworld", "1234", "data3", "data4", "data5", "data6", "data7", "data8",
# "data3b", "data4b", "data5b"]
第二行是包含:
values2 = values1 - values2
#=> ["helloworld", "1234", "data3", "data4", "data5", "data6", "data7", "data8",
加上values2_size #=> 3 空白字段。
我们可以使用CSV 方法将其写入文件,但这样做与使用常规文件方法相比并没有任何优势。我们可以简单地将以下字符串写入文件。
str = [(headers1 + headers2).join(';'),
values1.join(';'),
values2.join(';') + ';' * values2_size
].join("\n")
puts str
username;userid;full_name;follower_count;following_count;media_count;email;category;owner_profile_pic_url;media_url;tagged_brand_username
helloworld;1234;data3;data4;data5;data6;data7;data8;data3b;data4b;data5b
helloworld;1234;data3;data4;data5;data6;data7;data8;;;
让我们开始吧。
File.write(FILE_OUT, str)
#=> 265
请注意,如果 a 和 b 是数组,则 a += b 和 a -= b 分别扩展为 a = a + b 和 a = a - b。我使用的 CSV 方法记录在 here。
我将把它留给 OP 将我讨论过的操作组合成一个方法。