你能用关键字搜索数组吗?

时间:2014-04-06 02:26:04

标签: ruby arrays hash

如何使用["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中的行?

1 个答案:

答案 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) }