重写“更好”的代码

时间:2011-06-18 10:17:13

标签: ruby arrays coding-style initialization

我正在使用Ruby 1.9,我想知道是否有一种“更好”的方式来编写以下代码。

  array_one = []
  array_two = []
  some_array.each { |value|
    array_one << value.id
    array_two << value.name
  }

我“不喜欢”在上面的示例中初始化array_onearray_two,然后添加value.idvalue.name这是因为主要是为了更好地理解和阅读我的应用程序中的代码。

我想提供相同的功能,但具有“更好”的编码。有可能吗?

3 个答案:

答案 0 :(得分:5)

您所拥有的代码模式通常是fold(或更常见的 catamorphism )想要离开的明确标志。 Ruby确实提供了一种内置的折叠方法,由于历史原因,它被称为inject

未测试:

array_one, array_two = some_array.
  inject([[], []]) {|(array_one, array_two), value|
    [array_one << value.id, array_two << value.name]
}

不确定您是否认为这是“更好”。对于了解fold是什么的人来说,这可能更清楚。对于没有的人,可能不是。

(虽然我认为如果你了解fold是什么,那么你就不是一个非常优秀的Ruby程序员,甚至是一个非常优秀的程序员 at at所有,但这只是我的意见。)

然而,说某些迭代是fold并不是非常有用,因为fold是一种通用的迭代方法(这意味着每个形式的迭代可以表示为fold)。你真正所拥有的是map

array_one, array_two = some_array.map(&:id), some_array.map(&:value)

请注意,这将遍历some_array两次。但是,除非你有可靠的基准和分析结果表明这种双遍遍是你的应用程序中性能问题的主要来源,你真的不应该担心。

答案 1 :(得分:1)

您可以使用Array#collect方法:

array_one = some_array.collect { |value| value.id }
array_two = some_array.collect { |value| value.name }

正如JörgWMittag在他的回答中提到的,这个解决方案也将遍历源阵列两次。

答案 2 :(得分:1)

您可能希望使用transpose将包含两个元素数组的n元素数组转换为两个n元素数组:

array_one, array_two = some_array.map {|value| [value.id, value.name]}.transpose

这是RDoc link,虽然它相当简洁。