简体   繁体   English

Ruby-遍历不规则重复的哈希数组

[英]Ruby - iterate over array of irregularly repeating hashes

Example input array of hashes ( with some regular and irregular repeating pattern ) : 哈希输入示例数组(具有一些规则和不规则的重复模式):

[{ key1 => value1 }, { key2 => value2 }, { key3 => value3 }, 
 { key4 => value4 }, { key3 => value5 }, { key4 => value6 }, 
 { key1 => value7 }, { key2 => value8 }, { key3 => value9 }, 
 { key4 => value10 }, { key3 => value11 }, { key4 =>  value12 }, { key3  => value13 }, { key4 => value14 },
 { key1 => value15 }, { key2 => value16 }, { key3 =>   value17 }, { key4 => value18 } ]

Requirement is to convert the above to this : 要求是将以上内容转换为:

 [ [{ key1 => value1 }, { key2 => value2 },
    { key3key4 => value3value4value5value6 } ]
   [ { key1 => value7 }, { key2 => value8 }, 
     { key3key4 =>       value9value10value11value12value13value14 }]
   [ { key1 => value15 }, { key2 => value16 }, { key3key4 =>   value17value18 }] ]

( note, eg, key3key4 and value5value6value7value8 etc, are just concatenations of the keys and values ) (请注意,例如key3key4和value5value6value7value8等只是键和值的串联)

The input structure could be of any number of repeating hashes with key3 and key4 appearing irregularly, sometimes just two hashes, sometimes 3 etc.. 输入结构可以是任意数量的重复哈希,其中key3和key4不规则出现,有时只是两个哈希,有时是3个等等。

I understand array.each and array.map etc, and I think to achieve the above it may need counters or similar employed, but so far my efforts have quickly ended up in a tangled mess, hence posting here for some advice on how best to tackle this. 我了解array.each和array.map等,并且我认为要实现上述目标可能需要使用计数器或类似的工具,但是到目前为止,我的工作很快陷入了混乱,因此在此处发布了一些有关如何最好地解决问题的建议。解决这个问题。

Edit: a little more rationale, key3 and key4 ( and their values ) get concatenated as they are the keys where the hashes repeat ( irregularly ) in each loop of the pattern, and there is desire to collapse that down into one key:value pair hash in each 'repeat' of the pattern in the output. 编辑:更合理一点,key3和key4(及其值)被连接起来,因为它们是模式的每个循环中哈希值重复(不规则地)重复的键,并且希望将其折叠为一个key:value对散列输出中模式的每个“重复”。 The values are strings in real problem and it makes sense when they are concatenated 值是实际问题中的字符串,将它们串联时有意义

If the hashes repeat after all the key3 and key4 , then key1 will always be the first key, so we can use that and the slice_before method on arrays to split the array into the proper groupings: 如果在所有key3key4之后都重复散列,则key1将始终是第一个键,因此我们可以在阵列上使用该键和slice_before方法将数组拆分为适当的分组:

output = input.slice_before { |hash| hash.has_key?('key1') }

If the condition for a grouping isn't as simple as just 'always start with key1 , you can use slice_when to split a group when 2 adjacent hashes occur where the first contains a concatenate-able key and the second does not: 如果分组的条件并非总是以key1开头,那么可以使用slice_when在发生两个相邻的散列(其中第一个包含可连接的键,而第二个不包含可连接键)时拆分组。

output = input.slice_when do |current_hash, next_hash|
  concatenate_keys.any? { |key| current_hash.has_key?(key) } &&
    concatenate_keys.none? { |key| next_hash.has_key?(key) }
end 

From there, we just need to go through and collapse all key3 and key4 hashes into a single hash, which we can do with map , select and reject : 从那里,我们只需要遍历并将所有key3key4哈希折叠到一个哈希中,就可以使用mapselectreject

concatenate_keys = %w[key3 key4]
contains_concatenate_key = -> hash { concatenate_keys.any? { |key| hash.has_key?(key) } }

output = output.map do |grouping|
  concatenatable_hashes = grouping.select &contains_concatenate_key

  grouping.reject(&contains_concatenate_key) + [
    { concatenate_keys.join => concatenatable_hashes.flat_map(&:values).join }
  ]
end

p output
# => [[{"key1"=>"value1"}, {"key2"=>"value2"}, {"key3key4"=>"value3value4value5value6"}],
#     [{"key1"=>"value7"}, {"key2"=>"value8"}, {"key3key4"=>"value9value10value11value12value13value14"}],
#     [{"key1"=>"value15"}, {"key2"=>"value16"}, {"key3key4"=>"value17value18"}]]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM