Arrays Ruby排序以高效的方式使用另一个数组对哈希数组进行排序,因此处理时间是恒定的

Arrays Ruby排序以高效的方式使用另一个数组对哈希数组进行排序,因此处理时间是恒定的,arrays,ruby-on-rails,ruby,sorting,big-o,Arrays,Ruby On Rails,Ruby,Sorting,Big O,我有一些数据需要导出为csv。它目前大约有10000条记录,并将继续增长,因此我希望有一种高效的方法来进行迭代,特别是关于一个接一个地运行几个循环。 我的问题是,是否有一种方法可以避免我在下面描述的许多each循环,如果没有,我是否可以在Ruby的each/map旁边使用其他方法来保持处理时间不变,而不考虑数据大小 例如: 首先,我将循环遍历整个数据,以展平并重命名包含数组值的字段,这样,像issue that hol数组值这样的字段将变成issue_1和issue_1,如果它在数组中仅包含两个

我有一些数据需要导出为csv。它目前大约有10000条记录,并将继续增长,因此我希望有一种高效的方法来进行迭代,特别是关于一个接一个地运行几个循环。 我的问题是,是否有一种方法可以避免我在下面描述的许多each循环,如果没有,我是否可以在Ruby的each/map旁边使用其他方法来保持处理时间不变,而不考虑数据大小

例如:

首先,我将循环遍历整个数据,以展平并重命名包含数组值的字段,这样,像issue that hol数组值这样的字段将变成issue_1和issue_1,如果它在数组中仅包含两个项

接下来,我将执行另一个循环以获取哈希数组中的所有唯一键

使用第2步中的唯一键,我将执行另一个循环,使用不同的数组对这些唯一键进行排序,该数组保持键的排列顺序

最后是生成CSV的另一个循环

因此,我每次都使用Ruby的each/map对数据进行了4次迭代,完成此循环的时间将随着数据大小的增加而增加

原始数据如下表所示:

def data
  [
     {"file"=> ["getty_883231284_200013331818843182490_335833.jpg"], "id" => "60706a8e-882c-45d8-ad5d-ae898b98535f", "date_uploaded" => "2019-12-24", "date_modified" => "2019-12-24", "book_title_1"=>"", "title"=> ["haha"], "edition"=> [""], "issue" => ["nov"], "creator" => ["yes", "some"], "publisher"=> ["Library"], "place_of_publication" => "London, UK"]},

    {"file" => ["getty_883231284_200013331818843182490_335833.jpg"], "id" => "60706a8e-882c-45d8-ad5d-ae898b98535f", "date_uploaded" => "2019-12-24", "date_modified"=>"2019-12-24", "book_title"=> [""], "title" => ["try"], "edition"=> [""], "issue"=> ["dec", 'ten'], "creator"=> ["tako", "bell", 'big mac'], "publisher"=> ["Library"], "place_of_publication" => "NY, USA"}]
end
通过展平数组并重命名保存这些数组的键来重新映射日期

def csv_data
  @csv_data = [
     {"file_1"=>"getty_883231284_200013331818843182490_335833.jpg", "id"=>"60706a8e-882c-45d8-ad5d-ae898b98535f", "date_uploaded"=>"2019-12-24", "date_modified"=>"2019-12-24", "book_title_1"=>"", "title_1"=>"haha", "edition_1"=>"", "issue_1"=>"nov", "creator_1"=>"yes", "creator_2"=>"some", "publisher_1"=>"Library", "place_of_publication_1"=>"London, UK"},

    {"file_1"=>"getty_883231284_200013331818843182490_335833.jpg", "id"=>"60706a8e-882c-45d8-ad5d-ae898b98535f", "date_uploaded"=>"2019-12-24", "date_modified"=>"2019-12-24", "book_title_1"=>"", "title_1"=>"try", "edition_1"=>"", "issue_1"=>"dec", "issue_2" => 'ten', "creator_1"=>"tako", "creator_2"=>"bell", 'creator_3' => 'big mac', "publisher_1"=>"Library", "place_of_publication_1"=>"NY, USA"}]

end
对上述数据的标题进行排序

def csv_header

  csv_order = ["id", "edition_1", "date_uploaded",  "creator_1", "creator_2", "creator_3", "book_title_1", "publisher_1", "file_1", "place_of_publication_1", "journal_title_1", "issue_1", "issue_2", "date_modified"]

  headers_object = []
  sorted_header = []
  all_keys = csv_data.lazy.flat_map(&:keys).force.uniq.compact

  #resort using ordering by suffix eg creator_isni_1 comes before creator_isni_2
  all_keys = all_keys.sort_by{ |name| [name[/\d+/].to_i, name] }

  csv_order.each {|k| all_keys.select {|e| sorted_header << e if e.start_with? k} }

  sorted_header.uniq
end

生成csv还涉及更多循环:

def to_csv
  data = csv_data
  sorted_headers = csv_header(data)

  csv = CSV.generate(headers: true) do |csv|
    csv << sorted_header
    csv_data.lazy.each do |hash|
      csv << hash.values_at(*sorted_header)
    end
  end
end

老实说,我更感兴趣的是看我是否能够在没有进一步描述的情况下找到你想要的逻辑,而不仅仅是编程部分,但当然我也很喜欢,我做了一些Ruby,这是一个很好的复习。由于任务没有明确说明,因此必须通过阅读您的描述、输入数据和代码来提炼任务

我认为您应该做的是将所有内容都保存在非常基本和轻量级的阵列中,并在一大步读取数据的同时完成繁重的工作。 我还假设,如果一个键以一个数字结尾,或者一个值是一个数组,那么您希望它以{key}{n}的形式返回,即使只存在一个值

到目前为止,我提出了注释和

类自定义数据 @密钥数组结构 0:键 1:关联值的最大数量 2:数组是否在提要中找到{key}\n键, 提要中的or值是一个数组 @数据:是一个简单的数组数组 属性存取器:键,:数据 CSV\u订单=%w[ id版本日期\u上传创建者书籍\u标题出版商 文件位置\u出版物期刊\u标题发布日期\u修改 ] def初始化种子 @keys=CSV_ORDER.map{| key |[key,0,false]} @数据=[] feed.do每行| 新_行=[] 对键进行排序,以保持{key}{n}值的正确顺序 row.sort_by{| key,{u124; key}。每个do | key,值| 数组是否为false 如果键=~/\ud+$/ 如果密钥以数字结尾,则提取密钥 记住它是一个输出数组 key,is_array=key[/^.*.\u\d+$/,1],true 终止 如果value.u是a?大堆 如果value是数组,即使键没有以数字结尾, 对于输出,我们记住了这一点 数组=真吗 其他的 值=[值] 终止 查找键的位置(如果存在或为零) key|index=@keys.index{| a | a.first==key} if键索引 如果您可以有_n键和数组值的组合 对于提要中的密钥,您需要在此处更改此部分 考虑所有以前的值,这会增加一些复杂性 如果当前值的数量大于已保存的数量,请替代 @如果@keys[key\u index][1]@你是在问优化csv_头还是to_csv方法?我只是想理解在这个例子中N的意思。是记录的数量,还是键的数量?关于CVSY顺序的迭代,你是否认为它是固定时间的操作,因为它有固定数量的元素?两者都有。请你详细说明一下,我几乎不知道你想要什么。@Dominikowsiński谢谢。我已经更新了问题,使之更清楚。我想要的是找到一种方法来减少每个循环的数量。您将在更新的问题中看到,我每次都使用Ruby的each/map对数据进行4次迭代,完成此循环的时间将随着数据大小的增加而增加,我的问题是,有没有办法避免这种情况,如果没有的话,除了Ruby的each/map之外,还有什么其他方法可以让处理时间保持不变,而不管数据大小。@maxpleaner请参阅更新的问题
,希望它能让我想要的更清楚。非常感谢@wiesion,我已经对答案投了赞成票,并将进行实验。我将等待,看看是否有更多的答案,然后再选择一个。在这种情况下,CSV排序是一项功能要求,不仅是为了美观。如果您知道前面的所有标题,或者不知道的标题是按字母顺序追加的,这是一项简单的调整,只需预先填充@键,但结尾没有数字,我就更新了答案。