运行映射任务 处理新创建项值之一的正确第二数组方法是什么?



我有一个包含对象的数组:

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想要的正确方法";当[sportTagname[value]等于每个[any/some]personsport[item]的时,我想将[sportTagfound字段更改为true">。。。因此OP不需要实现嵌套的两次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; }