Arrays 重构:循环检索嵌套数组中的元素
我需要检查一个哈希数组,每个哈希包含一个标签和一个数据数组。最终结果将是一个连接的字符串,label first,后跟与该标签对应的数据 哈希的输入数组如下所示:Arrays 重构:循环检索嵌套数组中的元素,arrays,ruby,performance,refactoring,Arrays,Ruby,Performance,Refactoring,我需要检查一个哈希数组,每个哈希包含一个标签和一个数据数组。最终结果将是一个连接的字符串,label first,后跟与该标签对应的数据 哈希的输入数组如下所示: [{label:“第一”,数据:[1,2]},{label:“第二”,数据:[3,4,5]},{label:“第三”,数据:[]},{label:“第四”,数据:[6]}] 在本例中,max\u returns的值会很高,比如:10 def round_robin(arr, max_returns) result = '' i
[{label:“第一”,数据:[1,2]},{label:“第二”,数据:[3,4,5]},{label:“第三”,数据:[]},{label:“第四”,数据:[6]}]
在本例中,
max\u returns
的值会很高,比如:10
def round_robin(arr, max_returns)
result = ''
i = 0 # number of grabbed elements
j = 0 # inner array position
k = 0 # outer array position
l = 0 # number of times inner array length has been exceeded
while i < max_returns do
if k >= arr.length
j += 1
k = 0
end
element = arr[k]
if element[:data].empty?
k += 1
next
end
if j >= element[:data].length
l += 1
k += 1
if l > arr.length && i < max_returns
break
end
next
end
result += element[:label] + ': ' + element[:data][j].to_s + ', '
i += 1
k += 1
end
result
end
def循环(arr,max\u返回)
结果=“”
i=0#抓取的元素数
j=0#内部阵列位置
k=0#外部阵列位置
l=0#超出内部数组长度的次数
当我返回时
如果k>=arr.length
j+=1
k=0
结束
元素=arr[k]
如果元素[:数据].为空?
k+=1
下一个
结束
如果j>=元素[:数据].length
l+=1
k+=1
如果l>arr.length&&i
根据上述输入,输出应为:“第一:1,第二:3,第四:6,第一:2,第二:4,第二:5”
另外:max\u returns
是检索结果总数的最大数目。因此,如果我的示例有一个max\u returns=3
,那么输出应该是:“第一:1,第二:3,第四:6”
问题:是否有更好或更有效的方法以循环方式从多个阵列获取数据?我不确定什么是循环,但以下是提供您需要的输出的解决方案: 基于初始阵列元素移除的版本:
arr = [{label: "first", data: [1, 2]}, {label: "second", data: [3, 4, 5]}, {label: "third", data: []}, {label: "fourth", data: [6]}]
loop do
arr.each do |hash| # go through each hash
num = hash[:data].delete_at(0) # remove first element in data array
puts "#{hash[:label]}: #{num}" unless num.nil? # output it if it's not nil(means array was empty)
end
break if arr.map { |i| i[:data] }.flatten == [] # stop if all arrays are empty
end
不更改初始阵列的版本:
arr = [{label: "first", data: [1, 2]}, {label: "second", data: [3, 4, 5]}, {label: "third", data: []}, {label: "fourth", data: [6]}]
max_data_size = arr.map { |i| i[:data] }.map(&:size).max
loop.with_index do |_, i|
arr.each do |hash|
num = hash[:data][i]
puts "#{hash[:label]}: #{num}" unless num.nil?
end
break if i >= max_data_size - 1
end
如果没有最后两个连接,结果将是一个数组数组:
#⇒ [["first", 1], ["second", 3], ["fourth", 6],
# ["first", 2], ["second", 4], ["second", 5]]
arr=[{label:“first”,数据:[1,2]},
{标签:“第二”,数据:[3,4,5]},
{标签:“第三”,数据:[]},
{标签:“第四”,数据:[6]}]
labels,data=arr.map{h[:label],h[:data].dup]}.transpose
#=>[“第一”、“第二”、“第三”、“第四”]、[1,2]、[3,4,5]、[6]]
data.map(&:size).max.times.with_对象([])do | u,arr|
labels.each_index do|i|
d=数据[i]。移位
arr“第一:1,第二:3,第四:6,第一:2,第二:4,第二:5”
基准测试都是针对相同的数据运行的。我针对四种不同的场景运行了每个答案:*_5
是根据原始数据运行的:852,0,0,0*\u 500
针对相同的数据运行,但最多返回500次。*\u 2_5
针对4个数组中的数据运行,大小分别为:656、137、0、59,总共852条记录。*_2_500
针对arr2运行,最大返回值为500
user system total real
OP_5: 0.000000 0.000000 0.000000 ( 0.000120)
Mudasobwa_5: 0.000000 0.000000 0.000000 ( 0.000108)
Cary_5: 0.010000 0.000000 0.010000 ( 0.011316)
Rustam_5: 0.000000 0.000000 0.000000 ( 0.000087)
Wand_5: 0.010000 0.000000 0.010000 ( 0.003761)
Stefan_5: 0.000000 0.000000 0.000000 ( 0.004007)
OP_500: 0.010000 0.010000 0.020000 ( 0.017235)
Mudasobwa_500: 0.010000 0.000000 0.010000 ( 0.006164)
Cary_500: 0.010000 0.000000 0.010000 ( 0.011403)
Rustam_500: 0.010000 0.000000 0.010000 ( 0.011884)
Wand_500: 0.010000 0.000000 0.010000 ( 0.003743)
Stefan_500: 0.000000 0.000000 0.000000 ( 0.002711)
OP_2_5: 0.000000 0.000000 0.000000 ( 0.000052)
Mudasobwa_2_5: 0.000000 0.000000 0.000000 ( 0.000140)
Cary_2_5: 0.010000 0.000000 0.010000 ( 0.008196)
Rustam_2_5: 0.000000 0.000000 0.000000 ( 0.000088)
Wand_2_5: 0.000000 0.000000 0.000000 ( 0.003338)
Stefan_2_5: 0.010000 0.000000 0.010000 ( 0.002597)
OP_2_500: 0.000000 0.000000 0.000000 ( 0.002211)
Mudasobwa_2_500: 0.000000 0.000000 0.000000 ( 0.006373)
Cary_2_500: 0.010000 0.000000 0.010000 ( 0.008455)
Rustam_2_500: 0.020000 0.000000 0.020000 ( 0.019453)
Wand_2_500: 0.010000 0.000000 0.010000 ( 0.004846)
Stefan_2_500: 0.000000 0.000000 0.000000 ( 0.003421)
OP_avg: 0.002500 0.002500 0.005000 ( 0.004904)
Mudasobwa_avg: 0.002500 0.000000 0.002500 ( 0.003196)
Cary_avg: 0.010000 0.000000 0.010000 ( 0.009843)
Rustam_avg: 0.007500 0.000000 0.007500 ( 0.007878)
Wand_avg: 0.007500 0.000000 0.007500 ( 0.003922)
Stefan_avg: 0.002500 0.000000 0.002500 ( 0.003184)
与我之前的基准测试相反,平均值表明Stefan的答案实际上是最快的,比Mudasobwa的答案快了0.000012秒
注意:我不得不编辑一些答案,以模仿我的原始解决方案试图做的事情,因此在基准代码中有一些额外的东西是特意添加的。此外,一些解决方案没有使用
max_returns
限制(或者没有在限制处停止),这导致它们比其他解决方案花费的时间更长(我在最初问这个问题时责备自己的解释不够出色)。在选择答案时,我没有考虑到max_returns
的限制,因为只有我和Wand的答案才符合这一限制(详情请参见要点)
执行这些基准测试的代码和示例数据可在此处找到:
谢谢大家的回答 这将起作用:
arr = [{ label: "first", data: [1, 3] },
{ label: "second", data: [3, 4, 5] },
{ label: "third", data: [] },
{ label: "fourth", data: [6] }]
results = []
arr.each do |h|
h[:data].each_with_index do |d, i|
results[i] ||= []
results[i] << "#{h[:label]}: #{d}"
end
end
results.flatten.join(', ')
#=> "first: 1, second: 3, fourth: 6, first: 3, second: 4, second: 5"
arr=[{label:“first”,数据:[1,3]},
{标签:“第二”,数据:[3,4,5]},
{标签:“第三”,数据:[]},
{标签:“第四”,数据:[6]}]
结果=[]
arr.每个do | h|
h[:数据]。每个带有索引do | d的| u,i|
结果[i]| |=[]
结果[i]“第一:1,第二:3,第四:6,第一:3,第二:4,第二:5”
首先应该是秒:3
<代码>{label:“second”,数据:[“3”,“4”,“5”]}您是正确的,感谢您的发现!我修改了我的示例以匹配。round-robin
不是有效的方法名称,在结果中添加元素[:data][j]
时,似乎存在类型错误
string@Stefan你是对的,我匆忙创建了方法名和示例数据,但没有彻底检查它。我已经纠正了我的例子。谢谢你的基准测试(尽管我是最后一名)。报告基准测试时,最好包括基准测试代码(包括数据或生成数据的方法)。这样,读者可以在修改方法后运行基准测试。@Rustam的两种方法中,你使用了哪一种?为了使其与其他方法具有可比性,您应该使用第二种方法,它不会改变数组。@CarySwoveland我用更好的数据和Stefan的答案更新了基准测试。谢谢你的鼓励,我从这个问题中学到了很多,我也很开心。干杯@CarySwoveland哦,为了回答你之前的问题,我使用了Rustam答案的第二个版本;)读者们:斯特凡本可以把这篇文章写成一行,但他选择不这样做,可能是为了让读者更容易理解。压缩形式为:arr.each_with_object([]){h,results | h[:data]。each_with_index{d,i |(results[i]|=[])我在基准测试中使用了您的第二个版本。当我更改数据以更好地适应问题时,您的解决方案运行速度比第一次运行基准测试时慢了一点,因此我将答案更改为@stefan's。不过感谢您的回答!
user system total real
OP_5: 0.000000 0.000000 0.000000 ( 0.000120)
Mudasobwa_5: 0.000000 0.000000 0.000000 ( 0.000108)
Cary_5: 0.010000 0.000000 0.010000 ( 0.011316)
Rustam_5: 0.000000 0.000000 0.000000 ( 0.000087)
Wand_5: 0.010000 0.000000 0.010000 ( 0.003761)
Stefan_5: 0.000000 0.000000 0.000000 ( 0.004007)
OP_500: 0.010000 0.010000 0.020000 ( 0.017235)
Mudasobwa_500: 0.010000 0.000000 0.010000 ( 0.006164)
Cary_500: 0.010000 0.000000 0.010000 ( 0.011403)
Rustam_500: 0.010000 0.000000 0.010000 ( 0.011884)
Wand_500: 0.010000 0.000000 0.010000 ( 0.003743)
Stefan_500: 0.000000 0.000000 0.000000 ( 0.002711)
OP_2_5: 0.000000 0.000000 0.000000 ( 0.000052)
Mudasobwa_2_5: 0.000000 0.000000 0.000000 ( 0.000140)
Cary_2_5: 0.010000 0.000000 0.010000 ( 0.008196)
Rustam_2_5: 0.000000 0.000000 0.000000 ( 0.000088)
Wand_2_5: 0.000000 0.000000 0.000000 ( 0.003338)
Stefan_2_5: 0.010000 0.000000 0.010000 ( 0.002597)
OP_2_500: 0.000000 0.000000 0.000000 ( 0.002211)
Mudasobwa_2_500: 0.000000 0.000000 0.000000 ( 0.006373)
Cary_2_500: 0.010000 0.000000 0.010000 ( 0.008455)
Rustam_2_500: 0.020000 0.000000 0.020000 ( 0.019453)
Wand_2_500: 0.010000 0.000000 0.010000 ( 0.004846)
Stefan_2_500: 0.000000 0.000000 0.000000 ( 0.003421)
OP_avg: 0.002500 0.002500 0.005000 ( 0.004904)
Mudasobwa_avg: 0.002500 0.000000 0.002500 ( 0.003196)
Cary_avg: 0.010000 0.000000 0.010000 ( 0.009843)
Rustam_avg: 0.007500 0.000000 0.007500 ( 0.007878)
Wand_avg: 0.007500 0.000000 0.007500 ( 0.003922)
Stefan_avg: 0.002500 0.000000 0.002500 ( 0.003184)
arr = [{ label: "first", data: [1, 3] },
{ label: "second", data: [3, 4, 5] },
{ label: "third", data: [] },
{ label: "fourth", data: [6] }]
results = []
arr.each do |h|
h[:data].each_with_index do |d, i|
results[i] ||= []
results[i] << "#{h[:label]}: #{d}"
end
end
results.flatten.join(', ')
#=> "first: 1, second: 3, fourth: 6, first: 3, second: 4, second: 5"