如何使用["foo",1,2,3]
之类的数组并将其转换为可以通过关键字"foo"
快速搜索的内容?
我试图获取csv文件,并根据条件对其进行排序/过滤。例如,给出以下csv和标准:
foo,bar,foobar
1,2,3
4,5,6
7,8,9
@criteria = ["foobar", "foo"]
输出应该如下(顺序很重要):
foobar,foo
3,1
6,4
9,7
我使用嵌套循环检查@criteria
中与csv的每个index[0]
的每个项目。
require 'csv'
@criteria = ["foobar", "foo"]
@newcsv = []
csv = CSV.read("./foo.csv", { headers: true, return_headers: false })
csv = csv.to_a.transpose
@criteria.each do |n|
csv.each do |i|
if i[0] == n
@newcsv.push(i)
end
end
end
@newcsv = @newcsv.transpose
CSV.open("./transpose.csv", "wb") do |lines|
@newcsv.each { |line| lines << line }
end
它适用于小矩阵,但我确信它不会扩展。我想知道哈希是否会给我更好的表现。如何在不使用嵌套循环的情况下仅获取@criteria
中的行?
答案 0 :(得分:2)
所以这个答案是由其他用户发布的,后来被删除了,因为他或她讨厌它#34;但我认为它至少会为原始海报添加一些有用的信息,所以我在这里重新发布。
请注意,我不确定此代码的渐近性能是否比O(n^2)
矩阵的n * n
快,但原作者不同意我的观点。至少在这里是我的推理:
如果您有一个n * n
矩阵,并且您有n - 1
条件,那么创建索引就不会采用最差情况n-1 + n-2 + .. + 2 + 1 = O(n^2)
步骤,具体取决于如何对矩阵的标准和列进行排序?
然后你仍然需要收集n(n - 1)
个单元格,即使它是通过恒定时间数组索引访问。
这至少是我的推理。也许我错了。如果我是,请解释如何,以及下面代码的正确渐近运行时复杂性是什么!
扫描数组中的元素效率很低,但是一旦有了索引,就可以快速查找该索引处的元素。
根据标题行header = ["foo", "bar", "foobar"]
和@criteria = ["foobar", "foo"]
,您可以将它们转换为indices
:
indices = @criteria.map{|column| header.index(column)}
# => [2, 0]
然后,使用indices
,您可以映射行:
[
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
.map{|row| row.values_at(*indices)}
给出:
[
[3, 1],
[6, 4],
[9, 7],
]
这种方式,大多数计算复杂性在于创建indices
,它只执行一次,花在它上面的时间是可忽略的,其余的都是按索引查找的元素,并且复杂性很小,不像用户评论。
以下是使用上述方法的一些示例代码:
require 'csv'
@criteria = ['foobar', 'foo']
table = CSV.read('./foo.csv', headers: true)
indices = @criteria.map { |column| table.headers.index(column) }
table.map { |row| row.values_at(*indices) }