使用不同元素时,ruby中的flat_map

时间:2016-11-02 01:15:33

标签: ruby

我认为当你有一系列可变长度的哈希并且你想单独使用每个哈希时,flat_map很棒:

data = [
  {'apple' => 'fruit'},
  {'carrot' => 'vegetable'},
  {'orange' => 'fruit', 'pear' => 'fruit'},
  {'lettuce' => 'vegetable'}
] 

data.flat_map(&:to_a).reduce([]) {|acc, (k,v)| acc << Hash[k,v] }
 => [{"apple"=>"fruit"}, {"carrot"=>"vegetable"}, {"orange"=>"fruit"}, {"pear"=>"fruit"}, {"lettuce"=>"vegetable"}] 

但我不认为我完全理解flat_map。根据{{​​3}}:

  

返回一个新数组,其中包含运行块的连接结果   对于枚举中的每个元素都有一次。

但请看这个例子:

[[1], {a: "a"}, {b: "b"}].flat_map(&:to_a)
=> [1, [:a, "a"], [:b, "b"]] 

第一项从内部数组中剥离,其他项目将转换为数组。怎么知道这样做?

当我打电话给这样的时候:

[1].to_a
 => [1] 
[1].to_a.flatten
 => [1] 

您会看到结果与flat_map的结果不同。 flat_map在第一个例子中做什么来剥离数组的项目?

2 个答案:

答案 0 :(得分:2)

对于任何具有arr元素的数组m+n,如果

arr.map { ... }

返回

[a1, a2,.., am, o1, o2,.., on]

其中a1, a2,.., am是数组而o1, o2,.., on是除数组以外的对象,然后将map更改为flat_map,保持块不变,flat_map将返回

[*a1, *a2,.., *am, o1, o2,.., on]

示例1

有关

arr = [[1], {a: "a"}, {b: "b"}]

我们有

arr.map(&:to_a)
  #=> [[1], [[:a, "a"]], [[:b, "b"]]]

所以它遵循

arr.flat_map(&:to_a)

将返回

[*[1], *[[:a, "a"]], *[[:b, "b"]]]
  #=> [1, [:a, "a"], [:b, "b"]] 

确实确实如此。

示例2

现在假设我们有

arr = [1, 'cat', [2,3], {a: 4}]

然后

arr.map(&:itself)
  #=> [1, "cat", [2, 3], {:a=>4}]

所以

arr.flat_map(&:itself)
发现

返回

[1, "cat", 2, 3, {:a=>4}]

这是

的减少
[1, "cat", *[2, 3], {:a=>4}]

答案 1 :(得分:1)

[1].flatten[1] - 没有第二级。 [[1]].flatten[1]。这是您最后一个示例与所有其他示例之间的区别。

如果您先尝试普通map

[[1], {a: "a"}, {b: "b"}].map(&:to_a)
# => [[1], [[:a, "a"]], [[:b, "b"]]]

请注意,每个哈希都会数组化一个数组(每个数组都是一对键和一对值)。当你flatten一级时:

[[1], {a: "a"}, {b: "b"}].map(&:to_a).flatten(1)
# => [1, [:a, "a"], [:b, "b"]] 

这正是您使用flat_map所获得的。