Ruby 动态更新嵌套数组中的值
Posted
技术标签:
【中文标题】Ruby 动态更新嵌套数组中的值【英文标题】:Ruby dynamically updating value in nested array 【发布时间】:2022-01-22 12:00:03 【问题描述】:在 Ruby 中,使用 1D Array
,我可以通过在括号中传递 Integer
键来动态选择元素,如下所示:
example = [0,1,2,[3,4]]
i = 2
example[i]
==> 2
我想要实现的是通过传递Array
的Integers
来动态更新多维Array
中的元素,每个元素代表要在每个数组中选择的索引。我想要实现的示例:
example = [0,1,2,[3,4]]
path = [3, 1] (corresponds to the 4)
example[*path or some other syntax] = 9
example
==> [0,1,2,[3,9]]
我尝试的是存储每次路径迭代的结果:
temp = example
path.each |index|
temp = temp[index]
temp
==> 4
这成功识别了我要更新的元素。但是,它似乎存储了一个副本,而不是引用原始位置,如:
temp = 9
example
==> [0,1,2,[3,4]]
如何更新基本数组 example
而无需在单独的括号中硬编码 path
?
评论后澄清:我事先不知道path
的长度,这就是硬编码不可行的原因。
【问题讨论】:
example[3][1] = 9
还不够吗?
不,因为我希望能够容纳多个 path
长度。带括号的硬编码将我限制为两步 path
。
写一个方法。传入数组对象,然后是索引。您必须使您的方法能够接受任意数量的索引。
【参考方案1】:
您的迭代即将完成,您只需在运行path
之前停止一步,这样您就可以获得需要修改的数组而不是元素。
所以将path
拆分成你想要的部分:
*p, target = path
# [3], 1
然后使用#inject
查找数组:
ary = p.inject(example) |i, a| a[i]
# [3, 4]
然后做你的任务:
ary[target] = 9
当然,您需要添加一些逻辑来处理意外情况,例如 path
导致您进入非数组元素或 path
与 example
的结构不匹配(请考虑您的 path = [11, 6, 23]
示例)。
您也可以使用#dig
代替#inject
:
ary = example.dig(*p)
ary[target] = 9
# or
example.dig(*p)[target] = 9
这将解决一些有问题的path
s,如果ary.nil?
,您将不得不决定该怎么做。
【讨论】:
【参考方案2】:定义一个函数,类似于:
def deep_set! val, arr, *path
path[0...-1].each |i| arr = arr[i]
arr[path[-1]] = val
end
arr = [0,1,2,[3,4]]
deep_set! 9, arr, 3 ,1
arr #=> [0, 1, 2, [3, 9]]
【讨论】:
【参考方案3】:我假设path
至少包含一个元素。
你可以使用Array#dig。
def dig_and_replace(arr, path, replacement)
*first, last = path
if first.empty?
arr[last] = replacement
else
arr.dig(*first)[last] = replacement
end
arr
end
arr = [0,1,2,[3,4]]
dig_and_replace(arr,[3,1],99)
#=> [0,1,2,[3,99]]
arr
#=> [0,1,2,[3,99]]
dig_and_replace([0,1,2,[3, 4 ]],[3,1],
cat:'meow', dog:'woof')
#=> [0,1,2,[3,:cat=>"meow", :dog=>"woof"]]
dig_and_replace([0,[1,[2,3,[4,5,[6, 7],8],9],10,11]],[1,1,2,2,1],99)
#=> [0,[1,[2,3,[4,5,[6,99],8],9],10,11]]
dig_and_replace([0,[1,[2,3,[4,5,[6,7],8],9],10,11]],[1,1,2],99)
#=> [0,[1,[2,3, 99, 9],10,11]]
注意如果
path = [1,2,3,4]
*first, last = path
然后
first #=> [1,2,3]
last #=> 4
【讨论】:
以上是关于Ruby 动态更新嵌套数组中的值的主要内容,如果未能解决你的问题,请参考以下文章
MongoDB - 仅当嵌套数组中的所有条目存在时才更新它们