分配给所有哈希的值

时间:2017-08-03 14:37:17

标签: arrays ruby hash

我的脚本将一个元素(ticket [4])分配给一个哈希。

哈希数组看起来像这样

all = [{"hello"=>{"2014-01-02"=>0, "2014-01-03"=>0}}, {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}]

数组故障单看起来像这样

tickets = [["hello","2014-01-02","1","Clôturé","2"], ["hello","2014-01-03","1","Clôturé","1"]]

脚本运行后,应该以

结果
all = [{"hello"=>{"2014-01-02"=>2, "2014-01-03"=>1}}, {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}]

相反,我有

all = [{"hello"=>{"2014-01-02"=>2, "2014-01-03"=>1}}, {"bye"=>{"2014-01-02"=>2, "2014-01-03"=>1}}]

为所有键分配值2。我希望我的脚本只分配给一个特定的键"你好"在这种情况下而不是"你好"和" bye"

 tickets.each do |t|
    d_d = Date.strptime(t[1],"%d-%m-%Y")
    n_c = t[0].to_s
    all.each do |e|
        e.each do |nom,pair|
            pair.each do |d,tick|
                 d1 = Date.strptime(d,"%d-%m-%Y")
                 if n_c == nom.to_s && d1 == d_d
                 p pair[d] = t[4]
                end
            end
        end
    end
end

3 个答案:

答案 0 :(得分:0)

你可以这样做:

all = [{"hello"=>{"2014-01-02"=>0, "2014-01-03"=>0}}, {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}]
tickets = [["hello","2014-01-02","1","Clôturé","2"], ["hello","2014-01-03","1","Clôturé","1"]]

tickets.each do |ticket|
  # This is the same as:
  #  name = ticket[0]
  #  date = ticket[1]
  name, date = ticket[0..1]

  # Here we're finding the correct ticket in "all" array.
  # The "correct ticket" is the hash whose key is equal the "name"
  all_ticket = all.select { |h| h.keys.first == name }.first

  # If the "correct ticket" still doesn't have a count, we attribute 0 to it
  all_ticket[name][date] ||= 0

  # And here we're incrementing its count
  all_ticket[name][date] += ticket.last.to_i
end

# Prints the result
p all

答案 1 :(得分:0)

<强>代码

def aggregate(all, tickets)
  tickets_tot = tickets.each_with_object({}) { |(word, date, *_, nbr),h|
    h[[word, date]] = nbr.to_i }     
  all.map do |h|
    word, g = h.to_a.first
    f = g.each_with_object({}) { |(date,nbr),f| f[date] = nbr.to_i +
      tickets_tot.fetch([word, date], 0) }
    { word=>f }
  end
end

示例

对于问题中给出的alltickets

aggregate(all, tickets)
  #=> [{"hello"=>{"2014-01-02"=>2, "2014-01-03"=>1}},
  #    {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}]

下面

tickets_tot
  #=> {["hello", "2014-01-02"]=>2, ["hello", "2014-01-03"]=>1}

<强>解释

让我们逐步完成计算。

&GT;计算tickets_tot

出于效率原因,我们首先计算tickets_tot,因为这只需要通过tickets。另一种方法是为tickets的每个值枚举all

首先定义枚举器

enum = tickets.each_with_object({})
  #=> #<Enumerator: [["hello", "2014-01-02", "1", "Clôturé", "2"],
  #    ["hello", "2014-01-03", "1", "Clôturé", "1"]]:each_with_object({})>

生成enum的第一个元素,传递给块,并为块变量赋值。

(word, date, *_, nbr),h = enum.next
  #=> [["hello", "2014-01-02", "1", "Clôturé", "2"], {}]
word
  #=> "hello"
date
  #=> "2014-01-02"
_ #=> ["1", "Clôturé"]
nbr
  #=> "2"
h #=> {}

*_将变量_分配给datenbr之间所有值的数组。 (请注意,IRB将变量_用于其自身目的,因此它不会正确报告其值。)下划线用于表示此块变量未在块计算中使用。

哈希h最初为空,但在执行计算时会发生变化。

接下来执行块计算。

h[[word, date]] = nbr.to_i
h[["hello", "2014-01-02"]] = 2

enum生成的下一个和最后一个值现在传递给块。

(word, date, *_, nbr),h = enum.next
  #=> [["hello", "2014-01-03", "1", "Clôturé", "1"],
  #    {["hello", "2014-01-02"]=>2}]
word
  #=> "hello"
date
  #=> "2014-01-03"
_ #=> ["1", "Clôturé"]
nbr
  #=> "1"
h #=> {["hello", "2014-01-02"]=>2}

请注意h已更新。然后我们执行块计算。

h[[word, date]] = nbr.to_i
  #=> h[["hello", "2014-01-03"]] = 1

最后,

tickets_tot = h
  #=> {["hello", "2014-01-02"]=>2, ["hello", "2014-01-03"]=>1}

&GT;将all映射到所需的哈希数组

我们现在转到计算的第二部分。 all的第一个值传递给map块,块变量被赋值其值并执行块。

h = all[0]
  #=> {"hello"=>{"2014-01-02"=>0, "2014-01-03"=>0}}
a = h.to_a
  #=> [["hello", {"2014-01-02"=>0, "2014-01-03"=>0}]]
word, g = a.first
  #=> ["hello", {"2014-01-02"=>0, "2014-01-03"=>0}]
word
  #=> "hello"
g #=> {"2014-01-02"=>0, "2014-01-03"=>0}
f = g.each_with_object({}) { |(date,nbr),f| f[date] = nbr.to_i +
    tickets_tot.fetch([word, date], 0) }
  #=> {"2014-01-02"=>2, "2014-01-03"=>1}

请参阅Hash#fetch

{ word=>f }
  #=> {"hello"=>{"2014-01-02"=>2, "2014-01-03"=>1}}

这更新了第一个哈希值。最后,

h = all[1]
  #=> {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}
a = h.to_a
  #=> [["bye", {"2014-01-02"=>0, "2014-01-03"=>0}]]
word, g = a.first
  #=> ["bye", {"2014-01-02"=>0, "2014-01-03"=>0}]
word
  #=> "bye"
g #=> {"2014-01-02"=>0, "2014-01-03"=>0}
f = g.each_with_object({}) { |(date,nbr),f| f[date] = nbr.to_i +
    tickets_tot.fetch([word, date], 0) }
  #=> {"2014-01-02"=>0, "2014-01-03"=>0}

此时fetch的默认值为0

{ word=>f }
  # => {"bye"=>{"2014-01-02"=>0, "2014-01-03"=>0}}

此映射与初始哈希值保持不变。因此map返回给定的两个哈希数组。

答案 2 :(得分:0)

好的!该脚本运行良好,但ruby将日期视为同一个对象。我不得不添加&#34; .clone&#34;在创建包含所有日期的哈希时。

nom.each do |n|
    hash = {}
    hash = {n => dates.clone}
    all << hash
end