我对.each_with_object
在某种程度上的作用感到困惑。
例如:
("a".."c").each_with_object("") {|i,str| str << i} # => "abc"
另外:
(1..3).each_with_object(0) {|i,sum| sum += i} #=> 0
(因为整数是不可变的)。
在阅读Ruby文档中的示例后,我就是
混淆object()
内的参数实际上是什么。
关于以下flattify
代码:我对*
的使用感到困惑;为什么else语句只是element
? element
打算做什么?
def flattify(array)
array.each_with_object([]) do |element, flattened|
flattened.push *(element.is_a?(Array) ? flattify(element) : element)
end
end
答案 0 :(得分:1)
此处element
因此会获取每个array
元素的值
所有这段代码都只是递归地将所有嵌套数组放在初始数组中
但是Ruby内置了flatten
方法,它可以做同样的事情
例如
ar = [1, 2, [3, 4, [5, 6]]]
ar.flatten
#=> [1, 2, 3, 4, 5, 6]
只是与您的flattify
flattify ar
#=> [1, 2, 3, 4, 5, 6]
答案 1 :(得分:1)
传递给object()
的参数充当迭代之间的中间值的累加器。在进入每次迭代时,它将作为flattened
参数传递。
*
是 splat 运算符。它将数组转换为传递给push
方法的参数列表。
答案 2 :(得分:1)
var custom_lenguajes ="";
$(document).on('pageinit', '#page-1', function() {
// get lenguajes. START
$.getJSON( parser_origin + "/_country/spain/v134/lacarte.restaurants.front/alacarte/php/languages.front.php", { site: id_establecimiento()}, function(data){
for (var i=0, len=data.length; i < len; i++) {
console.log(data[i]);
}
data = data['data'];
data3 = data;
$.each(data3, function(entryIndex, entry) {
$.each(this.lenguajes, function() {
alert(this.code); // don't show nothing. ONLY TEST
custom_lenguajes += this.code + "\,";
console.log(custom_lenguajes); //show "". ONLY TEST
});
});
});
});
答案 3 :(得分:0)
与
#each_with_object
做什么相混淆
如果您先查看#each_with_object
,您可能会更好地理解#inject
。 #each_with_object
与#inject
类似。 http://blog.krishnaswamy.in/blog/2012/02/04/ruby-inject-vs-each-with-object/中的示例,包括:
#using inject
[[:tom,25],[:jerry,15]].inject({}) do |result, name_and_age|
name, age = name_and_age
result[name] = age
result
end
=> {:tom=>25, :jerry=>15}
#using each_with_object
[[:tom,25],[:jerry,15]].each_with_object({}) do |name_and_age, result|
name, age = name_and_age
result[name] = age
end
=> {:tom=>25, :jerry=>15}
请参阅此要点以获取示例测试:https://gist.github.com/cupakromer/3371003
深度文章:http://engineering-blog.alphasights.com/tap-inject-and-each_with_object/
<强>更新强>
#inject
而不是#each_with_object
在此展平代码中工作吗?
是的,见下文。我已经说明性地重构了您的展平代码以使用#inject
。另外,我删除了对&#34; splat&#34;的依赖。运算符(http://ruby-doc.org/core-2.3.1/doc/syntax/calling_methods_rdoc.html#label-Array+to+Arguments+Conversion)
# Flattens nested array; uses `Enumerable#inject`
# @see http://ruby-doc.org/core-2.3.1/Enumerable.html#method-i-inject
# @param arg [Array] contains objects of any type including any amount of nested arrays.
# @raise [StandardError] if arg is not Array class
# @return [Array] flat array comprised of elements from arg.
# @example
# flattify([nil, [1, [:two, [3.0], {4=>5}], "6"]]) #=> [nil, 1, :two, 3.0, {4=>5}, "6"]
def flattify(arg)
raise "arg is not Array" unless arg.is_a?(Array)
# variable ret_var used here to illustrate method's return in verbose fasion
# supplied [] used as initial value for flattened_array
ret_var = arg.inject([]) do |flattened_array, element|
# check if element class is Array
if element.is_a?(Array)
# Array#concat because flattify returns Array
# same as: a = a + b
# same as: a += b
flattened_array.concat(
# recursively call flattify with element as arg
# element is an Array
flattify(element)
)
else
# Array#push because element is not an Array
# same as: a << b
flattened_array.push(element)
end
# used in next iteration as value for first arg above in: "|flattened_array, element|"
# OR returned on last iteration, becoming value of ret_var above
flattened_array
end
# explicit return for illustrative purposes
return ret_var
end
更新2
可能[我]问为什么在这里使用splat运算符?我还是有点 对此感到困惑。似乎代码每次都在循环播放 它在扁平数组中,是什么?*?
flattened.push *(element.is_a?(Array) ? flattify(element) : element)
上述块是一个&#34;三元操作&#34; (参见:https://en.wikipedia.org/wiki/Ternary_operation),这里解释:https://stackoverflow.com/a/4252945/1076207如此:
if_this_is_a_true_value ? then_the_result_is_this : else_it_is_this
将flattify
示例相互比较:
# each_with_object
flattened.push *(flattify(element))
# inject
flattened_array.concat(flattify(element))
此处*
splat运算符(请参阅:https://stackoverflow.com/search?q=%5Bruby%5D+splat)与Array#concat
执行相同的操作。但是,splat允许flattened.push
接受三元操作返回的两种可能类型之一:1)数组;或2)无论element
是什么。有关说明,请注意splat运算符如何阻止嵌套:
# each_with_object with splat
flattened = [1,2,3]
flattened.push *([4,5,6]) # => [1, 2, 3, 4, 5, 6]
flattened.push *(7) # => [1, 2, 3, 4, 5, 6, 7]
# each_with_object without splat
flattened = [1,2,3]
flattened.push ([4,5,6]) # => [1, 2, 3, [4, 5, 6]]
flattened.push (7) # => [1, 2, 3, [4, 5, 6], 7]
相反,Array#concat
只会接受一个数组。如果使用相同的三元操作并返回一个元素,则会导致错误:
# inject
flattened_array = [1,2,3]
flattened_array.concat([4,5,6]) # => [1, 2, 3, 4, 5, 6]
flattened_array.concat(7) # => TypeError: no implicit conversion of Fixnum into Array
总之,flattify
的两个版本都实现了相同的结果。但是,#each_with_object
使用#push
,三元运算和splat运算符; #inject
使用if / else语句,#concat
和#push
。
更新3
当我们用
object([])
做每个时,最后一个参数变为了 阵列。
是。它变成了一个数组,并且在整个迭代过程中继续是相同的数组,直到它被传回。
所以
inject
第一个成为数组?
是。第一个成为传入的数组,但仅用于第一次迭代,然后它被每个后续迭代的代码块结果替换。
我们的代码如何知道元素是否被定义为int和 flattened_Array是一个数组?
element.is_a?(Array) # => true or false
当元素为Array
class时,此方法返回true
,否则返回false
。 false
表示除了包含int
的数组之外的任何内容。
有关详细信息,请参阅:http://ruby-doc.org/core-2.3.1/Object.html#method-i-is_a-3F