Ruby俱乐部将两个多维键通过日期和其他键元素转换为1

时间:2018-07-05 12:08:11

标签: ruby sinatra

我刚刚开始研究红宝石Sinatra。

从现有数组创建数组时遇到问题。
我有一个按日期分组的数组,每个元素都包含当天的所有条目。

{
    "2015-05-15": [{
        "minutes": 25,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        }],
        "key6": "2015-05-15"
    }, {
        "minutes": 25,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        }],
        "key6": "2015-05-15"
    }],
    "2015-05-25": [{
        "minutes": 25,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        }],
        "key6": "2015-05-25"
    }],
    "2015-06-10": [{
        "minutes": 25,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        }],
        "key6": "2015-06-10"
    }, {
        "minutes": 25,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        }],
        "key6": "2015-06-10"
    }]
}

我想组合这个数组,以便每个日期都通过键安排所有子元素数组。例如,以下数组是我要寻找的。在这里,日期2015-05-15中的所有子数组都合并为一个关键元素。

 {
    "2015-05-15": [{
        "minutes": 50,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        },
        {
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        },{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        },
        {
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        },
        [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        },
        {
            "some key": "0.6"
        }],
        "key6": "2015-05-15"
    }],
    "2015-05-25": [{
        "minutes": 50,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        },
        {
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        },{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        },
        {
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        },
        [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        },
        {
            "some key": "0.6"
        }],
        "key6": "2015-05-25"
    }],
    "2015-06-10": [{
        "minutes": 50,
        "key1": [{
            "some key1": "14",
            "some key": "subject here"
        },
        {
            "some key1": "14",
            "some key": "subject here"
        }],
        "key2": [{
            "some key": "0/0"
        },{
            "some key": "0/0"
        }],
        "key3": [{
            "some key": "5/5"
        },
        {
            "some key": "5/5"
        }],
        "key4": [{
            "some key": 0.48
        },
        [{
            "some key": 0.48
        }],
        "key5": [{
            "some key": "0.6"
        },
        {
            "some key": "0.6"
        }],
        "key6": "2015-06-10"
    }]
}

我尝试使用我创建的自定义方法来排列它们。

def self.iterateArray(array)
    result = Hash.new  #{ |h, k| h[k] = [] }
    count =  0
    result[count] = Array.new(7)

    array.each { |key, data|

      result[count]["date"] = key
      data.each { |k, d| 

        k.each { |key_, data1|
          if key_ == 'key1'
            result[count][key_] += data1
          end
          if key_ == 'key2'
            result[count][key_] << data1
          end
          if key_ == 'key3'
            result[count][key_] << data1
          end
          if key_ == 'key4'
            result[count][key_] << data1
          end
          if key_ == 'key5'
            result[count][key_] << data1
          end
          if key_ == 'key6'
            result[count][key_] << data1
          end
        }
      }
      count += 1
    }
    puts "result: #{result}"  
    result
  end

但是每次我尝试运行此方法时,都会出现类似

的奇怪错误,例如“没有将字符串隐式转换为整数”
result[count]["date"] = key

之前,它在result[count]处产生了这样的错误,但是后来我用

result[count] = Hash.new { |h, k| h[k] = [] }

然后系统开始指向下一个元素。

谁能告诉我我做错了什么?或者告诉我如何处理此类问题或如何创建自定义数组。感谢您的帮助。

伙计们,我为在此添加2个“ key2”元素表示歉意。实际上是key1 ..到key6元素。我已经更新了示例数组。

3 个答案:

答案 0 :(得分:0)

您的问题中的问题

  • 每个哈希(输入和输出)中都有两次键"key2"。因此,后一个将覆盖第一个分配的值。以Engineersmnky为例:{key2: 1, key2: 2} #=> {key2: 2}

  • 您尚未说明将输入转换为输出的完整逻辑。

  • 不知道是否要考虑值的类型(例如IntegerArray等)来准备生成的哈希,还是特定于键的值,即始终汇总键的值"minutes",而无需检查其类型。

解决方案

因此,尽管我不确定您期望的输出背后的逻辑,但是我能够将原始数组转换为它:

输入:

input = {
  "2015-05-15" => [{
    "minutes" => 25,
    "key1" => [{
        "some key1" => "14",
        "some key" => "subject here"
    }],
    "key2" => [{
        "some key" => "5/5"
    }],
    "key3" => [{
        "some key" => 0.48
    }],
    "key4" => [{
        "some key" => "0.6"
    }],
    "key5" => "2015-05-15"
}, {
    "minutes" => 25,
    "key1" => [{
        "some key1" => "14",
        "some key" => "subject here"
    }],
    "key2" => [{
        "some key" => "5/5"
    }],
    "key3" => [{
        "some key" => 0.48
    }],
    "key4" => [{
        "some key" => "0.6"
    }],
    "key5" => "2015-05-15"
}],
"2015-05-25" => [{
    "minutes" => 25,
    "key1" => [{
        "some key1" => "14",
        "some key" => "subject here"
    }],
    "key2" => [{
        "some key" => "5/5"
    }],
    "key3" => [{
        "some key" => 0.48
    }],
    "key4" => [{
        "some key" => "0.6"
    }],
    "key5" => "2015-05-25"
}],
"2015-06-10" => [{
    "minutes" => 25,
    "key1" => [{
        "some key1" => "14",
        "some key" => "subject here"
    }],
    "key2" => [{
        "some key" => "5/5"
    }],
    "key3" => [{
        "some key" => 0.48
    }],
    "key4" => [{
        "some key" => "0.6"
    }],
    "key5" => "2015-06-10"
}, {
    "minutes" => 25,
    "key1" => [{
        "some key1" => "14",
        "some key" => "subject here"
    }],
    "key2" => [{
        "some key" => "5/5"
    }],
    "key3" => [{
        "some key" => 0.48
    }],
    "key4" => [{
        "some key" => "0.6"
    }],
    "key5" => "2015-06-10"
  }]
}

过程:

output = {}

input.each do |date, ary|
  keys = ary.map(&:keys).flatten.uniq    # Returns all the keys in all the hash elements for given date

  hash = {}

  keys.each do |key|
    if ary.all? { |e| e[key].is_a?(Integer) }
      hash[key] = ary.inject(0) { |sum, h| sum + h[key].to_i }    # Assuming you want to sum up values for keys with integer values
    elsif ary.all? { |e| e[key].is_a?(Array) }
      hash[key] = ary.inject([]) { |sum, h| sum + h[key] }        # Assuming you need `+` operation on the array values too 
    elsif ary.all? { |e| e[key].is_a?(String) }
      hash[key] = ary[0][key]                                     # Assuming string values are same in all the elements of array
    else
      raise "Invalid type for value of key: #{key}"
    end
  end
  output[date] = [hash]     # I don't know why are we putting it in array as it will always be one element only. You could do: `output[date] = hash`
end

输出:

output
 => {"2015-05-15"=>[{
       "minutes"=>50,
       "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
                {"some key1"=>"14", "some key"=>"subject here"}],
       "key2"=>[{"some key"=>"5/5"}, {"some key"=>"5/5"}],
       "key3"=>[{"some key"=>0.48}, {"some key"=>0.48}],
       "key4"=>[{"some key"=>"0.6"}, {"some key"=>"0.6"}],
       "key5"=>"2015-05-15"}],
     "2015-05-25"=>[{
       "minutes"=>25,
       "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
       "key2"=>[{"some key"=>"5/5"}],
       "key3"=>[{"some key"=>0.48}],
       "key4"=>[{"some key"=>"0.6"}],
       "key5"=>"2015-05-25"
     }],
     "2015-06-10"=>[{
       "minutes"=>50,
       "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
                {"some key1"=>"14", "some key"=>"subject here"}],
       "key2"=>[{"some key"=>"5/5"}, {"some key"=>"5/5"}],
       "key3"=>[{"some key"=>0.48}, {"some key"=>0.48}],
       "key4"=>[{"some key"=>"0.6"}, {"some key"=>"0.6"}],
       "key5"=>"2015-06-10"
     }]
   }

答案 1 :(得分:0)

代码

def convert(h)
  h.each_with_object(Hash.new { |e,k| e[k]={} }) do |(date, v),f|
    v.each { |g| f[date].update(g) { |_,ov,nv|ov.is_a?(Array) ? ov+nv : ov } }
  end
end

示例

由于示例的大小和格式较大,因此难以识别树木的森林。我所做的第一件事是将示例简化为基本结构。我将键(日期字符串)的数量从三个减少到了两个,并减少了每个哈希中的键的数量。我还使用缩进来阐明结构。这样,我获得了以下内容。

h = {
  "2015-05-15"=>[
    { "minutes"=>25,
      "key1"=>[{ "some key1"=>"14", "some key"=>"subject here" }],
      "key2"=>[{ "some key"=>"5/5"}],
      "key5"=>"2015-05-15"
    },
    { "minutes"=>25,
      "key1"=>[{ "some key1"=>"14", "some key"=>"subject here" }],
      "key2"=>[{ "some key"=>"5/5" }],
      "key4"=>[{ "some key"=>"0.6" }],
      "key5"=>"2015-05-15"
    }
  ],
  "2015-06-10"=>[
    { "minutes"=>25,
      "key1"=>[{ "some key1"=>"14", "some key"=>"subject here" }],
      "key2"=>[{ "some key"=>"5/5" }],
      "key5"=>"2015-06-10"
    },
    { "minutes"=>25,
      "key1"=>[{ "some key1"=>"14", "some key"=>"subject here" }],
      "key2"=>[{ "some key"=>"5/5"}]
    }
  ]
}

convert(h)
  #=> { "2015-05-15"=>{
  #       "minutes"=>25, 
  #       "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
  #                {"some key1"=>"14", "some key"=>"subject here"}],
  #       "key2"=>[{"some key"=>"5/5"},
  #            {"some key"=>"5/5"}],
  #       "key5"=>"2015-05-15",
  #       "key4"=>[{"some key"=>"0.6"}]},
  #     "2015-06-10"=>{
  #       "minutes"=>25,
  #       "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
  #                {"some key1"=>"14", "some key"=>"subject here"}],
  #       "key2"=>[{"some key"=>"5/5"},
  #                {"some key"=>"5/5"}],
  #       "key5"=>"2015-06-10"
  #     }
  #   }

此结果与要求的结果略有不同。每个日期字符串键(例如"2015-05-15")的值将是一个包含单个元素(哈希)的数组。这样做的目的是始终包含单个元素,因此我通过将日期字符串的值设为哈希值来简化了此操作。

说明

Hash.new { |h,k| h[k]={} }使h[k]没有键h时,k被设置为等于空散列。请参见采用块的Hash::new形式。

我使用了Hash#update(又名merge!) that employs a block to determine the values of keys that are present in both hashes being merged. See the doc for the values of the three block variables, k (common key), ov ("*old value*") and nv`(“ 新值”)的形式< / p>

该代码大致等于以下内容。

f = {}
h.each do |date, v|
  v.each do |g|
    f[date] = {} unless f.key?(date)
    f[date].update(g) { |_,ov,nv| ov.is_a?(Array) ? ov+nv : ov }
  end
end
f

如果仍然不清楚,请尝试运行此代码并添加一些puts语句。

f = {}
h.each do |date, v|
  puts "date=#{date}"
  puts "v=#{v}"
  puts "f=#{f}"
  v.each do |g|
    puts "  f=#{g}"
      if f.key?(date)
        puts "  f has key date=#{date} so f[#{date}] is not set to {}"
      else
        puts "  f does not has key date=#{date} so f[#{date}] is to {}"
      end
    f[date] = {} unless f.key?(date)
    f[date].update(g) { |_,ov,nv| ov.is_a?(Array) ? ov+nv : ov }
    puts "  f[#{date}]= #{f[date]}"
  end
end
f

这将打印以下内容。

date=2015-05-15
v=[{"minutes"=>25, "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}], 
                   "key2"=>[{"some key"=>"5/5"}], "key5"=>"2015-05-15"},
   {"minutes"=>25, "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
                   "key2"=>[{"some key"=>"5/5"}], "key4"=>[{"some key"=>"0.6"}],
                   "key5"=>"2015-05-15"}]
f={}
f={"minutes"=>25, "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
                  "key2"=>[{"some key"=>"5/5"}], "key5"=>"2015-05-15"}
f does not has key date=2015-05-15 so f[2015-05-15] is to {}
f[2015-05-15]= {"minutes"=>25,
                "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
                "key2"=>[{"some key"=>"5/5"}], "key5"=>"2015-05-15"}
f={"minutes"=>25, "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
                  "key2"=>[{"some key"=>"5/5"}],
                  "key4"=>[{"some key"=>"0.6"}],
                  "key5"=>"2015-05-15"}
f has key date=2015-05-15 so f[2015-05-15] is not set to {}
f[2015-05-15]= {"minutes"=>25,
                "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
                         {"some key1"=>"14", "some key"=>"subject here"}],
                "key2"=>[{"some key"=>"5/5"},
                         {"some key"=>"5/5"}],
                "key5"=>"2015-05-15",
                "key4"=>[{"some key"=>"0.6"}]}

date=2015-06-10
v=[{"minutes"=>25,
    "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
    "key2"=>[{"some key"=>"5/5"}],
    "key5"=>"2015-06-10"},
       {"minutes"=>25,
        "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
        "key2"=>[{"some key"=>"5/5"}]}]
f={"2015-05-15"=>{"minutes"=>25,
                  "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}, 
                          {"some key1"=>"14", "some key"=>"subject here"}],
                  "key2"=>[{"some key"=>"5/5"},
                          {"some key"=>"5/5"}],
                  "key5"=>"2015-05-15", 
                  "key4"=>[{"some key"=>"0.6"}]}}
f={"minutes"=>25,
   "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
   "key2"=>[{"some key"=>"5/5"}],
   "key5"=>"2015-06-10"}
f does not has key date=2015-06-10 so f[2015-06-10] is to {}

f[2015-06-10]= {"minutes"=>25,
                "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
                "key2"=>[{"some key"=>"5/5"}], "key5"=>"2015-06-10"}
f={"minutes"=>25,
   "key1"=>[{"some key1"=>"14", "some key"=>"subject here"}],
   "key2"=>[{"some key"=>"5/5"}]}
f has key date=2015-06-10 so f[2015-06-10] is not set to {}
f[2015-06-10]= {"minutes"=>25,
                "key1"=>[{"some key1"=>"14", "some key"=>"subject here"},
                         {"some key1"=>"14", "some key"=>"subject here"}], 
                "key2"=>[{"some key"=>"5/5"}, {"some key"=>"5/5"}], 
                "key5"=>"2015-06-10"}

答案 2 :(得分:0)

我使用我创建的这种方法实现了答案。在这里,我已经删除了“日期”字段,因为它越来越重复。

 def self.iterateArray(array)
    response = []
    array.each { |key, data|
      result = Hash.new { |h, k| h[k] = [] }

      result["date"] = key
      result["minutes"] =0
      result["key1"] =[]
      result["key2"] =[]
      result["key3"] =[]
      result["key4"] =[]
      result["key5"] =[]
      data.each { |k, d| 

        k.each { |key1, data1|
          if key1 == "minutes"
            result[key1] += data1
          elsif key1 != "date"
            result[key1] << data1[0]
          end
        }
      }
      response << result
    }
    response
  end

但是我仍然不喜欢在向变量添加值之前需要在数组中声明所有变量的方式。有什么解决办法吗?