搜索深度嵌套数组以更新对象
Search a deeply nested array to update an object
我有一个深度嵌套的数据结构,我有兴趣在我的数组(和数组数组)中匹配某个值,然后将一些数据推送到伴随的数组中。例如,下面是我的 colors 数组,伴随的是 moreColors 数组,它可能存在也可能不存在:
var myData = [{
"color": "green",
"moreColors": [
{
"color": "beige"
},
{
"color": "black",
"moreColor": [
{
"color": "grey"
},
{
"color": "white",
"moreColors": [...]
}
]
}
]
}]
我有兴趣在我的数组中搜索颜色值 grey 并向该对象添加 moreColors 数组 moreColors: [{"color" : "blue"}]
。在某些情况下,如果数组已经存在,这可能会使用 push() 方法。我将如何最好地实现这一目标?我的目标是在这里添加值和 update/mutate myData 数组,因为这将传递给另一个函数。此处的嵌套可以有几层深,因此循环内的简单循环将无法工作。递归函数在这里最有效吗?我也愿意接受更好的方法或使用像 underscore 或 lodash 这样的库。虽然我更喜欢香草 js 版本。下面是我开始的递归解决方案,但是代码不会 运行 超过一个级别。
findNested(myData, "grey")
function findNested(myArray, color) {
myArray.moreColors?.forEach(element => {
if(element.color !== color){
if(element.moreColors.length > 0) {
findNested(element.moreColors, color);
}
} else {
element.moreColors.push({
"color": "blue"
});
}
});
}
这是我认为您正在尝试的一个简单示例。
findNestedColorObject()
接受一个数组和一个要搜索的颜色字符串和 returns 第一个 color
属性 匹配的对象。
updateMoreColors()
接受上面返回的对象,如果不存在则先赋值 moreColors
,然后推送到数组。
function findNestedColorObject(array, color) {
let colorObject;
for (const obj of array) {
if (obj.color === color) {
colorObject = obj;
break;
}
if (obj.moreColors !== undefined) {
colorObject = findNestedColorObject(obj.moreColors, color);
}
}
return colorObject;
}
function updateMoreColors(colorObject, colors) {
colorObject.moreColors ??= [];
for (const color of [].concat(colors)) {
colorObject.moreColors.push({ color });
}
}
const myData = [{ "color": "green", "moreColors": [{ "color": "beige" }, { "color": "black", "moreColors": [{ "color": "grey" }, { "color": "white", "moreColors": ["ochre"] }] }] }];
const greyObject = findNestedColorObject(myData, 'grey');
console.log('found:')
console.log(greyObject);
updateMoreColors(greyObject, 'purple');
console.log('updated:');
console.log(greyObject);
const beigeObject = findNestedColorObject(myData, 'beige');
console.log('found:')
console.log(beigeObject);
updateMoreColors(beigeObject, ['salmon', 'crimson']);
console.log('updated:');
console.log(beigeObject);
或者,由于您的尝试似乎是在同一个函数中进行搜索和更新,您可以将上述两个函数结合起来。 (这将继续更新所有匹配的对象,而不仅仅是第一个)。
function updateNestedColorObject(array, color, moreColors) {
for (const obj of array) {
if (obj.color === color) {
obj.moreColors ??= [];
for (const color of [].concat(moreColors)) {
obj.moreColors.push({ color });
}
}
if (obj.moreColors !== undefined) {
updateNestedColorObject(obj.moreColors, color, moreColors);
}
}
}
const myData = [{ "color": "green", "moreColors": [{ "color": "beige" }, { "color": "black", "moreColors": [{ "color": "grey" }, { "color": "white", "moreColors": ["ochre"] }] }] }];
updateNestedColorObject(myData, 'grey', 'purple');
updateNestedColorObject(myData, 'purple', 'beige');
updateNestedColorObject(myData, 'beige', ['salmon', 'crimson']);
console.log(myData);
对不起,有些深渊我是不会让自己沉下去的。我不会帮你做像改变原始数据这样野蛮的事情。
但是如果您对从旧结构创建新结构的版本感兴趣,并且在适当的位置添加了额外的颜色节点,我们可以编写一个相当简单的递归:
const addColor = (target, newColor) => (xs) =>
xs .map (({color, moreColors = []}) => ({
color,
... (color == target
? {moreColors: addColor (target, newColor) (moreColors) .concat ({color: newColor})}
: moreColors .length > 0
? {moreColors: addColor (target, newColor) (moreColors)}
: {}
)
}))
const myData = [{color: "green", moreColors: [{color: "beige"}, {color: "black", moreColors: [{color: "grey"}, {color: "white", moreColors: [{color: "..."}]}]}]}]
console .log (addColor ('grey', 'blue') (myData))
// console .log (myData) // uncomment to see that the original has not been folded, spindled, or mutilated
.as-console-wrapper {max-height: 100% !important; top: 0}
我们映射数组,保持颜色 属性 不变,然后以三种方式之一处理 moreColors
:
- 如果
color
匹配我们的目标颜色,我们会在 moreColors
节点上重复出现,并向其附加我们的附加颜色。 (如果缺少此节点,我们将其默认为空数组。)
- 如果没有,并且我们有现有的
moreColor
个条目,我们会重复使用它们
- 如果没有,我们将完全跳过
moreColor
节点。
你好,检查一下我刚刚制作的这个函数,它真的很短,我认为它真的很好,我不知道什么是“递归”,但我在一个非常嵌套的对象数组上测试了它,我认为它也适用于对象看看输出:)
编辑:我找到了一个更好的方法,它不删除数据,而是 RETURNS 一个排序的 OBJ/OR 数组(你可以将其中一个传递给这个函数进行排序)请提供反馈
var myData = [{
"color": "green",
"moreColors": [
{
"color": "blue"
},
{
"color": "blue",
"moreColor": [
{
"color": "blue"
},
{
"color": "blue",
"moreColors": []
}
]
}
]
},['blue'],"blue"]
function searchArrOrObj(objOrArray,color,newColor) {
let arrayOrObj = Object.assign((objOrArray.constructor===Array?[]:{}), objOrArray)
for (item in arrayOrObj) {
if (arrayOrObj[item]===color) {
arrayOrObj[item] = newColor;
} else if (typeof arrayOrObj[item]==='object') {
arrayOrObj[item] = searchArrOrObj(arrayOrObj[item],color,newColor)
}
}
return arrayOrObj;
}
let newData = searchArrOrObj(myData,"blue","red")
console.log(myData)
console.log(newData)
我有一个深度嵌套的数据结构,我有兴趣在我的数组(和数组数组)中匹配某个值,然后将一些数据推送到伴随的数组中。例如,下面是我的 colors 数组,伴随的是 moreColors 数组,它可能存在也可能不存在:
var myData = [{
"color": "green",
"moreColors": [
{
"color": "beige"
},
{
"color": "black",
"moreColor": [
{
"color": "grey"
},
{
"color": "white",
"moreColors": [...]
}
]
}
]
}]
我有兴趣在我的数组中搜索颜色值 grey 并向该对象添加 moreColors 数组 moreColors: [{"color" : "blue"}]
。在某些情况下,如果数组已经存在,这可能会使用 push() 方法。我将如何最好地实现这一目标?我的目标是在这里添加值和 update/mutate myData 数组,因为这将传递给另一个函数。此处的嵌套可以有几层深,因此循环内的简单循环将无法工作。递归函数在这里最有效吗?我也愿意接受更好的方法或使用像 underscore 或 lodash 这样的库。虽然我更喜欢香草 js 版本。下面是我开始的递归解决方案,但是代码不会 运行 超过一个级别。
findNested(myData, "grey")
function findNested(myArray, color) {
myArray.moreColors?.forEach(element => {
if(element.color !== color){
if(element.moreColors.length > 0) {
findNested(element.moreColors, color);
}
} else {
element.moreColors.push({
"color": "blue"
});
}
});
}
这是我认为您正在尝试的一个简单示例。
findNestedColorObject()
接受一个数组和一个要搜索的颜色字符串和 returns 第一个 color
属性 匹配的对象。
updateMoreColors()
接受上面返回的对象,如果不存在则先赋值 moreColors
,然后推送到数组。
function findNestedColorObject(array, color) {
let colorObject;
for (const obj of array) {
if (obj.color === color) {
colorObject = obj;
break;
}
if (obj.moreColors !== undefined) {
colorObject = findNestedColorObject(obj.moreColors, color);
}
}
return colorObject;
}
function updateMoreColors(colorObject, colors) {
colorObject.moreColors ??= [];
for (const color of [].concat(colors)) {
colorObject.moreColors.push({ color });
}
}
const myData = [{ "color": "green", "moreColors": [{ "color": "beige" }, { "color": "black", "moreColors": [{ "color": "grey" }, { "color": "white", "moreColors": ["ochre"] }] }] }];
const greyObject = findNestedColorObject(myData, 'grey');
console.log('found:')
console.log(greyObject);
updateMoreColors(greyObject, 'purple');
console.log('updated:');
console.log(greyObject);
const beigeObject = findNestedColorObject(myData, 'beige');
console.log('found:')
console.log(beigeObject);
updateMoreColors(beigeObject, ['salmon', 'crimson']);
console.log('updated:');
console.log(beigeObject);
或者,由于您的尝试似乎是在同一个函数中进行搜索和更新,您可以将上述两个函数结合起来。 (这将继续更新所有匹配的对象,而不仅仅是第一个)。
function updateNestedColorObject(array, color, moreColors) {
for (const obj of array) {
if (obj.color === color) {
obj.moreColors ??= [];
for (const color of [].concat(moreColors)) {
obj.moreColors.push({ color });
}
}
if (obj.moreColors !== undefined) {
updateNestedColorObject(obj.moreColors, color, moreColors);
}
}
}
const myData = [{ "color": "green", "moreColors": [{ "color": "beige" }, { "color": "black", "moreColors": [{ "color": "grey" }, { "color": "white", "moreColors": ["ochre"] }] }] }];
updateNestedColorObject(myData, 'grey', 'purple');
updateNestedColorObject(myData, 'purple', 'beige');
updateNestedColorObject(myData, 'beige', ['salmon', 'crimson']);
console.log(myData);
对不起,有些深渊我是不会让自己沉下去的。我不会帮你做像改变原始数据这样野蛮的事情。
但是如果您对从旧结构创建新结构的版本感兴趣,并且在适当的位置添加了额外的颜色节点,我们可以编写一个相当简单的递归:
const addColor = (target, newColor) => (xs) =>
xs .map (({color, moreColors = []}) => ({
color,
... (color == target
? {moreColors: addColor (target, newColor) (moreColors) .concat ({color: newColor})}
: moreColors .length > 0
? {moreColors: addColor (target, newColor) (moreColors)}
: {}
)
}))
const myData = [{color: "green", moreColors: [{color: "beige"}, {color: "black", moreColors: [{color: "grey"}, {color: "white", moreColors: [{color: "..."}]}]}]}]
console .log (addColor ('grey', 'blue') (myData))
// console .log (myData) // uncomment to see that the original has not been folded, spindled, or mutilated
.as-console-wrapper {max-height: 100% !important; top: 0}
我们映射数组,保持颜色 属性 不变,然后以三种方式之一处理 moreColors
:
- 如果
color
匹配我们的目标颜色,我们会在moreColors
节点上重复出现,并向其附加我们的附加颜色。 (如果缺少此节点,我们将其默认为空数组。) - 如果没有,并且我们有现有的
moreColor
个条目,我们会重复使用它们 - 如果没有,我们将完全跳过
moreColor
节点。
你好,检查一下我刚刚制作的这个函数,它真的很短,我认为它真的很好,我不知道什么是“递归”,但我在一个非常嵌套的对象数组上测试了它,我认为它也适用于对象看看输出:) 编辑:我找到了一个更好的方法,它不删除数据,而是 RETURNS 一个排序的 OBJ/OR 数组(你可以将其中一个传递给这个函数进行排序)请提供反馈
var myData = [{
"color": "green",
"moreColors": [
{
"color": "blue"
},
{
"color": "blue",
"moreColor": [
{
"color": "blue"
},
{
"color": "blue",
"moreColors": []
}
]
}
]
},['blue'],"blue"]
function searchArrOrObj(objOrArray,color,newColor) {
let arrayOrObj = Object.assign((objOrArray.constructor===Array?[]:{}), objOrArray)
for (item in arrayOrObj) {
if (arrayOrObj[item]===color) {
arrayOrObj[item] = newColor;
} else if (typeof arrayOrObj[item]==='object') {
arrayOrObj[item] = searchArrOrObj(arrayOrObj[item],color,newColor)
}
}
return arrayOrObj;
}
let newData = searchArrOrObj(myData,"blue","red")
console.log(myData)
console.log(newData)