gpt4 book ai didi

ruby - 为什么在对 CSV 中的 2 列进行哈希处理时出现错误 `stack level too deep (systemstackerror)`?

转载 作者:数据小太阳 更新时间:2023-10-29 08:03:24 25 4
gpt4 key购买 nike

这是我的代码,应该对 fotoFd.csv 中的 2 列进行哈希处理,然后将哈希处理后的列保存在单独的文件 T4Friendship.csv 中:

require "csv"

arrayUser=[]
arrayUserUnique=[]
arrayFriends=[]

fileLink = "fotoFd.csv"

f = File.open(fileLink, "r")
f.each_line { |line|
row = line.split(",");
arrayUser<<row[0]
arrayFriends<<row[1]
}

arrayUserUnique = arrayUser.uniq
arrayHash = []

for i in 0..arrayUser.size-1

arrayHash<<arrayUser[i]
arrayHash<<i

end

hash = Hash[arrayHash.each_slice(2).to_a]

array1 =hash.values_at *arrayUser

array2 =hash.values_at *arrayFriends

fileLink = "T4Friendship.csv"


for i in 0..array1.size-1
logfile = File.new(fileLink,"a")
logfile.print("#{array1[i]},#{array2[i]}\n")
logfile.close
end

第一列包含用户,第二列包含他们的 friend 。所以,我希望它在 T4Friendship.csv 中生成类似这样的内容:

1 2
1 4
1 10
1 35
2 1
2 8
2 11
3 28
3 31
...

最佳答案

问题是一个大数组splat展开引起的。 splat * 可用于将数组扩展为参数列表。参数在堆栈上传递。如果参数太多,您将耗尽堆栈空间并出现上述错误。

这是 irb 中问题的一个快速演示,它在调用 puts 时试图分解一百万个元素的数组:

irb
irb(main):001:0> a = [0] * 1000000; nil # Use nil to suppress statement output
=> nil
irb(main):002:0> puts *a
SystemStackError: stack level too deep
from /usr/lib/ruby/1.9.1/irb/workspace.rb:80
Maybe IRB bug!
irb(main):003:0>

您似乎正在处理大型 CSV 文件,因此您的 arrayUser 数组非常大。用splat展开大数组导致线上的问题:

array1 =hash.values_at *arrayUser

您可以通过在 arrayUser 上调用 map 并在一个 block 中转换每个值来避免 splat:

array1 = arrayUser.map{ |user| hash[user] }


建议代码

您的代码似乎将名称映射到唯一的 ID 号。输出似乎与输入的格式相同,只是名称被转换为 ID 号。你可以做到这一点,而无需保留任何数组来消耗内存,只需使用在读取过程中构建的单个散列,并用于将名称动态转换为数字。代码如下所示:

def convertCsvNamesToNums(inputFileName, outputFileName)
# Create unique ID number hash
# When unknown key is lookedup, it is added with new unique ID number
# Produces a 0 based index
nameHash = Hash.new { |hash, key| hash[key] = hash.size }
# Convert input CSV with names to output CSV with ID numbers
File.open(inputFileName, "r") do |inputFile|
File.open(outputFileName, 'w') do |outputFile|
inputFile.each_line do |line|
# Parse names from input CSV
userName, friendName = line.split(",")
# Map names to unique ID numbers
userNum = nameHash[userName]
friendNum = nameHash[friendName]
# Write unique ID numbers to output CSV
outputFile.puts "#{userNum}, #{friendNum}"
end
end
end
end

convertCsvNamesToNums("fotoFd.csv", "T4Friendship.csv")

注意:此代码会在遇到用户和 friend 时为其分配 ID 号。您之前的代码只为用户分配 ID 号,然后查找好友。我建议的代码将确保为 friend 分配 ID 号,即使他们从未出现在用户列表中。数字顺序与您提供的略有不同,但我认为这并不重要。

您还可以将内部循环体缩短为:

        # Parse names from input, map to ID numbers, and write to output
outputFile.puts line.split(",").map{|name| nameHash[name]}.join(',')

为了便于阅读,我想我会单独包含此更改。


更新代码

根据您在评论中的要求,这里的代码优先考虑 ID 号的用户列。只有在第一列完全处理后,ID 号才会分配给第二列中的条目。它首先传递一次输入,将第一列添加到散列中,然后第二次传递输入以像以前一样处理它,使用第一次传递中预先准备好的散列。如果 friend 列包含用户列中任何地方都不存在的新条目,则仍可以在第二遍中添加新条目。

def convertCsvNamesToNums(inputFileName, outputFileName)
# Create unique ID number hash
# When unknown key is lookedup, it is added with new unique ID number
# Produces a 0 based index
nameHash = Hash.new { |hash, key| hash[key] = hash.size }
# Pass over the data once to give priority to user column for ID numbers
File.open(inputFileName, "r") do |inputFile|
inputFile.each_line do |line|
name, = line.split(",") # Parse name from line, ignore the rest
nameHash[name] # Add name to unique ID number hash (if it doesn't already exist)
end
end
# Convert input CSV with names to output CSV with ID numbers
File.open(inputFileName, "r") do |inputFile|
File.open(outputFileName, 'w') do |outputFile|
inputFile.each_line do |line|
# Parse names from input, map to ID numbers, and write to output
outputFile.puts line.split(",").map{|name| nameHash[name]}.join(',')
end
end
end
end

convertCsvNamesToNums("fotoFd.csv", "T4Friendship.csv")

关于ruby - 为什么在对 CSV 中的 2 列进行哈希处理时出现错误 `stack level too deep (systemstackerror)`?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33066859/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com