我有一个包含对象的数组:
let sportTag = [
{ id: 1, name: 'FOOTBALL', found: false },
{ id: 2, name: 'TENNIS' , found: false },
{ id: 3, name: 'BASKET' , found: false },
]
我还有另一个包含对象的数组,每个对象都有一个作为数组的字段(sports
):
let person = [{
id: 1,
name: "Mark",
age: 23,
sports: ["volleyball", "rugby", "tennis"],
}, {
id: 2,
name: "Rupert",
age: 40,
sports: ["golf"],
}, {
id: 3,
name: "John",
age: 31,
sports: ["football", "golf", "rugby", "tennis"],
}]
当sportTag名称等于每个人的运动时,我想将sportTag查找字段更改为true。我尝试了嵌套地图
const result = sportTag.map(st => {
person.map(p => {
p.sports.map(s => {
if (st.name.toLocaleUpperCase() === s.toLocaleUpperCase()) {
return {
...st, found: true
}
}
return s
})
return p
})
return st
})
console.log(sportTag)
//OUTPUT
// { id: 1, name: 'FOOTBALL', found: false },
// { id: 2, name: 'TENNIS' , found: false },
// { id: 3, name: 'BASKET' , found: false }
console.log(result)
//OUTPUT
// { id: 1, name: 'FOOTBALL', found: false },
// { id: 2, name: 'TENNIS' , found: false },
// { id: 3, name: 'BASKET' , found: false }
为什么result
中没有反映这些变化?我预计输出为:
{ id: 1, name: 'FOOTBALL', found: true },
{ id: 2, name: 'TENNIS' , found: true },
{ id: 3, name: 'BASKET' , found: false }
您的代码的问题是,对于第一个map
的每次迭代,您总是返回st
,因此您会得到原始值。
你可能想要这样的东西:
const result = sportTag.map(st => {
const foundSport = person.find(p =>
p.sports.find(s => st.name.toLocaleUpperCase() === s.toLocaleUpperCase())
);
return foundSport
? { ...st, found: true }
: st;
});
console.log(sportTag)
// { id: 1, name: 'FOOTBALL', found: false },
// { id: 2, name: 'TENNIS', found: false },
// { id: 3, name: 'BASKET', found: false }
console.log(result)
// { id: 1, name: 'FOOTBALL', found: true },
// { id: 2, name: 'TENNIS', found: true },
// { id: 3, name: 'BASKET', found: false }
根据以上注释。。。
OP已经在问题描述中提到了实现OP想要的正确方法";当[
sportTag
的name
[value]等于每个[any
/some
]person
的sport
[item]的时,我想将[。。。因此OP不需要实现嵌套的两次sportTag
的found
字段更改为true
">map
而是实现map
/some
任务。
但是(尤其是对于较大的数据量),可以选择一种基于查找的方法,该方法适用于Map
实例,而不是遵循上面建议的方法,即在每个map
迭代中对每个嵌套的some
任务进行额外的再次迭代。映射任务本身将非常简单。对于后者,甚至可以选择一种使映射与当前查找的变量/常量名称不可知的实现,因为可以将其引用作为map
方法的第二个thisArg
参数。
原因之一是可以用较少的迭代周期来实现查找创建。但一旦完成,就永远不会成为性能瓶颈。
function createLookupOfAnyPracticedSport(persons) {
return new Map(
// (5) create a map as lookup for unique sport items.
Array
// (3) create array from set of step (2)
.from(
new Set(
// (2) create a set of unique sport
// items/values as of step (1)
persons
// (1) concatenate array of all `sports`
// practiced by any person.
.reduce((result, { sports }) =>
result.concat(sports), []
)
)
)
// (4) sanitize and map the unique sport items/values
// in order to qualify as entries for step (5) ...
.map(sport => [sport.toLocaleUpperCase(), true])
);
}
function createUpToDateSportTagFromBoundSports(tagItem) {
const allSportsLookup = this;
// create (updated) shallow copy of the original
// sport tag item in order to not directly mutate
// such an item's original reference.
return {
...tagItem,
found: allSportsLookup
.has(tagItem.name.toLocaleUpperCase())
};
}
const personList = [{
id: 1, name: "Mark", age: 23,
sports: ["volleyball", "rugby", "tennis"],
}, {
id: 2, name: "Rupert", age: 40,
sports: ["golf"],
}, {
id: 3, name: "John", age: 31,
sports: ["football", "golf", "rugby", "tennis"],
}];
const sportTagList = [{
id: 1, name: 'FOOTBALL', found: false,
}, {
id: 2, name: 'TENNIS', found: false,
}, {
id: 3, name: 'BASKET', found: false,
}];
const mappedTagList = sportTagList
.map(
createUpToDateSportTagFromBoundSports,
createLookupOfAnyPracticedSport(personList),
);
console.log({
mappedTagList,
sportTagList,
personList,
});
console.log(
'entries of any practiced sport ...',
[...createLookupOfAnyPracticedSport(personList).entries()],
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
let person = [{
id: 1, name: "Mark", age: 23,
sports: ["volleyball", "rugby", "tennis"],
}, {
id: 2, name: "Rupert", age: 40,
sports: ["golf"],
}, {
id: 3, name: "John", age: 31,
sports: ["football", "golf", "rugby", "tennis"],
}];
let sportTag = [{
id: 1, name: 'FOOTBALL', found: false,
}, {
id: 2, name: 'TENNIS', found: false,
}, {
id: 3, name: 'BASKET', found: false,
}];
sportTag.forEach((elem, index, array) => {
person.forEach((el, i, arr) => {
if (person[i].sports.indexOf(sportTag[index].name.toLocaleLowerCase()) != -1) {
sportTag[index].found = true;
}
});
});
console.log(sportTag);
.as-console-wrapper { min-height: 100%!important; top: 0; }