【问题标题】:how to convert array of arrays (from reading a csv file) into a hash如何将数组数组(从读取 csv 文件)转换为哈希
【发布时间】:2013-04-12 19:55:41
【问题描述】:

读取一个csv文件后,我有这样的数据结构:

[["name1 | value1 | value2 | value3 | value4 "],
 ["name2 | value1 | value2 | value3 | value4 "],...]

我需要将其转换为哈希,如下所示:

{"name1" => "value1 | value2 | value3 | value4", 
 "name2" => "value1 | value2 | value3 | value4",...}

或者,更好:

{"name1" => ["value1","value2","value3","value4"],
 "name2" => ["value1","value2","value3","value4"],...}

我找到了许多将数组数组转换为哈希的方法,但没有一种方法将内部数组中的第一个元素用作哈希的键。

谁能提出一个优雅的解决方案?

【问题讨论】:

    标签: ruby arrays csv hash


    【解决方案1】:
    rows = [["name1 | value1 | value2 | value3 | value4 "],
            ["name2 | value1 | value2 | value3 | value4 "],]
    
    h = Hash[
       rows.flatten.
       map { |r| r = r.split('|').map(&:strip); [r.first, r.drop(1)] }
    ]
    
    # => {"name1"=>["value1", "value2", "value3", "value4"],
    #     "name2"=>["value1", "value2", "value3", "value4"]}
    

    我有点好奇您是如何得出这种输入结构的。如果您阅读带有分隔符“|”的 CSV,您可能会从以下内容开始:

    [["name1", "value1", "value2", "value3", "value4"],
     ["name2", "value1", "value2", "value3", "value4"]]
    

    外部地图中的r = r.split('|').map(&:strip) 是要转换成的。 如果您确实有这种形式,则转换为哈希会简单得多:

    Hash[ rows.map { |r| [r.first, r.drop(1)] } ]
    

    【讨论】:

    • 或使用 splat 运算符:Hash[rows.map { |name, *values| [name, values] }]
    • @Stefan 你的评论应该是一个独立的答案。
    • @sawa 我已将其发布为答案。
    【解决方案2】:

    除了@dbenhur 的回答。假设 CSV 类可以处理分隔符,并且您得到如下基本结构:

    rows = [["name1", "value1", "value2", "value3", "value4"],
            ["name2", "value1", "value2", "value3", "value4"]]
    

    您可以使用 splat 运算符对其进行转换:

    Hash[rows.map { |name, *values| [name, values] }]
    # => {"name1"=>["value1", "value2", "value3", "value4"], "name2"=>["value1", "value2", "value3", "value4"]}
    

    【讨论】:

      【解决方案3】:
      def to_hash(a)
        h = {}
        a.each do |item|
          a2 = item.first.strip.split(' | ')
          h[a2.shift] = a2
        end
        h
      end
      

      用法:

      a = [["name1 | value1 | value2 | value3 | value4 "],
           ["name2 | value1 | value2 | value3 | value4 "]]
      to_hash(a)
      # => {"name1"=>["value1", "value2", "value3", "value4"],
      #     "name2"=>["value1", "value2", "value3", "value4"]}
      

      【讨论】:

        【解决方案4】:

        你可以试试这个:

        csv.inject({}) do |memo, item|
            parts = item.first.split('|').map(&:strip)
            memo[parts.first] = parts.slice(1,parts.size)
            memo
        end
        

        给你{"name1" => ["value1","value2","value3","value4"], "name2" => ["value1","value2","value3","value4"],...}

        附带说明一下,每当我编写像 memo[parts.first] = parts.slice(1,parts.size) 这样的代码时,我真的希望 Ruby 只添加一个 headtail 方法。

        【讨论】:

        • 在 Ruby 中,headfirsttaildrop(1),或者使用 head, *tail = list 获取它们。
        猜你喜欢
        • 2012-12-21
        • 1970-01-01
        • 2012-10-29
        • 2019-10-27
        • 2019-05-23
        • 2015-11-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多