将多种方法的结果推入数组的干净方法

时间:2018-07-23 01:32:36

标签: ruby refactoring

我有以下Ruby代码,它使用不同的参数多次调用同一函数,并将结果压入一个公共数组。

people_relations = []
people.zip(people_addresses).map do |person, address|
  people_relations.push(createRelation(person, address))
end
people.zip(people_ph_numbers).map do |person, phone_number|
  people_relations.push(createRelation(person, phone_number))
end
people.zip(people_aliases).map do |person, _alias|
  people_relations.push(createRelation(person, _alias))
end

def createRelation(e1, e2)
  [true, false].sample ? CurrentRelation.new(e1, e2) : PastRelation.new(e1, e2)
end

这段代码可以很好地工作,但是我觉得这不是Ruby惯用的方式,可以通过将代码压缩成更少的行或使其看起来更简洁来改进。

是否有更好的方法编写上面显示的代码?

2 个答案:

答案 0 :(得分:2)

您可以创建一个包含将要使用的所有人员“属性”的数组,并使用Enumerable#each_with_object可以分配一个初始数组,以填充每次对createRelation()的调用的结果:< / p>

attributes = [people_addresses, people_ph_numbers, people_aliases]
relations = people.each_with_object([]).with_index do |(person, memo), index|
  attributes.each do |attribute|
    memo << createRelation(person, attribute[index])
  end
end

答案 1 :(得分:1)

为此,我可能会使用transpose-> flat_map解决方案,例如:

def CreateRelation(person, relationship)
  if [true, false].sample
    "#{person} is currently related to #{relationship}"
  else
    "#{person} used to be related to #{relationship}"
  end
end

people = ['Person 1', 'Person 2', 'Person 3']
addresses = ['Person 1 Address', 'Person 2 Address', 'Person 3 Address']
phone_numbers = ['Person 1 Phone', 'Person 2 Phone', 'Person 3 Phone']
aliases = ['Person 1 AKA', 'Person 2 AKA', 'Person 3 AKA']

我们可以将这4个数组粘贴到单个数组中,然后transpose,这样每个数组的第一个元素就彼此以数组结尾,第二个元素以另一个数组结尾,最后一个以三分之一结尾:< / p>

[people, addresses, phone_numbers, aliases].transpose # => [
#  ["Person 1", "Person 1 Address", "Person 1 Phone", "Person 1 AKA"],
#  ["Person 2", "Person 2 Address", "Person 2 Phone", "Person 2 AKA"],
#  ["Person 3", "Person 3 Address", "Person 3 Phone", "Person 3 AKA"]]

,然后您可以通过致电flat_map CreateRelation

result = [people, addresses, phone_numbers, aliases].transpose.flat_map do |person, *relations|
  relations.map { |relationship| CreateRelation(person, relationship) }
end
#["Person 1 used to be related to Person 1 Address",
# "Person 1 used to be related to Person 1 Phone",
# "Person 1 used to be related to Person 1 AKA",
# "Person 2 is currently related to Person 2 Address",
# "Person 2 used to be related to Person 2 Phone",
# "Person 2 is currently related to Person 2 AKA",
# "Person 3 is currently related to Person 3 Address",
# "Person 3 used to be related to Person 3 Phone",
# "Person 3 used to be related to Person 3 AKA"]

或者,如果您不想map / flat_map,那么在那一点上,您可以坚持迭代和推送。


我考虑得越多,我就越倾向于使用transpose-> each_with_object,而不是flat_map ...更少“创建一个数组然后抛出”,尽管我将其保留在flat_map中,因为它是另一种选择,并且@Sebastian Palma已涵盖each_with_object