就像这些数据
const persons = [
{
label: "jhon",
value: 1
},
{
label: "Mary",
value: 2
},
{
label: "Michelle",
value: 3
},
{
label: "David",
value: 4
},
{
label: "Kerry",
value: 5
},
{
label: "Tom",
value: 6
}
];
const testPassedPersons = [3, 5, 6];
我想做什么?
我需要移动这些人谁包括testpasssedpersons号码数组的头部。
所以现在Michelle/Kerry/Tom应该移动,value从小到大的顺序[3,5,6]
我需要得到什么
const SortedPersons = [
{
label: "Michelle",
value: 3
},
{
label: "Kerry",
value: 5
},
{
label: "Tom",
value: 6
}
{
label: "jhon",
value: 1
},
{
label: "Mary",
value: 2
},
{
label: "David",
value: 4
},
];
我已经尝试过了
实际上我有一个解决方案,但我想知道其他更好的方法(特别是更短或更快)
这是我的路
const sortedPersons = [
...persons.filter((person) => testPassedPersons.includes(person.value)),
...persons.filter((person) => !testPassedPersons.includes(person.value))
];
▼codesandbox url。https://codesandbox.io/s/pensive-david-1giqnk?file=/src/index.js
结果如下:
let sortedPersons = new Set();
testPassedPersons.forEach((passedPerson) => {
persons.forEach((person) => {
if (passedPerson === person.value) {
sortedPersons.add(person);
}
});
});
persons.forEach((person) => sortedPersons.add(person));
sortedPersons = [...sortedPersons];
console.log(sortedPersons);
如代码所示,我正在创建一个集合,因为集合将只保存唯一的值。我们添加具有testpasssedpersons中值的人员,然后添加其余人员。因为set包含唯一的项,所以不会发生重复。最后,将该集合转换为数组。
您可以用所需的顺序构建对象并按value
排序或将项移到底部。
此方法允许将任何未知项/value
移动到顶部(值小于0),底部(值较大,如Number.MAX_VALUE
)或仅在给定顺序之间。
const
persons = [{ label: "jhon", value: 1 }, { label: "Mary", value: 2 }, { label: "Michelle", value: 3 }, { label: "David", value: 4 }, { label: "Kerry", value: 5 }, { label: "Tom", value: 6 }],
testPassedPersons = [3, 5, 6],
order = Object.fromEntries(testPassedPersons.map((v, i) => [v, i + 1]));
persons.sort((a, b) => (order[a.value] || Number.MAX_VALUE) - (order[b.value] || Number.MAX_VALUE));
console.log(persons);
.as-console-wrapper { max-height: 100% !important; top: 0; }
我不认为你目前的方法有什么问题。您可以使用分区函数而不是过滤器函数来节省遍历数组的循环。
配分函数的思想是将匹配结果推入第一个数组(相当于过滤器结果),然后将所有其他结果推入第二个数组,因此您有两个数组,一个匹配结果和一个不匹配结果。
许多JS库都有分区函数,例如Lodash和Ramda。
const persons = [{ label: "jhon", value: 1 }, { label: "Mary", value: 2 }, { label: "Michelle", value: 3 }, { label: "David", value: 4 }, { label: "Kerry", value: 5 }, { label: "Tom", value: 6 }];
const testPassedPersons = [3, 5, 6];
const partition = (data, partition_function) =>
data.reduce(
(acc, val) => (acc[+!partition_function(val)].push(val), acc),
[[], []]
);
const get_sorted_persons = persons =>
partition(persons, (person) => testPassedPersons.includes(person.value)).flat();
console.log(get_sorted_persons(persons));
您可以编写自定义排序函数。indexOf
返回-1
如果元素不在数组中。
因此,如果aIndex
不是-1,bIndex
是-1,这意味着没有找到。因此保持a和b的原始顺序。
如果aIndex
仅为-1,我们返回1意味着a应该在b之后。
如果bIndex
仅为-1,我们返回-1意味着a应该在b之前(b在a之后)。所以基本上在testPassedPersons
中没有找到的是在之后。
最后indexA - indexB
将根据符号决定哪个先出现。
const persons = [ { label: "jhon", value: 1 }, { label: "Mary", value: 2 }, { label: "Michelle", value: 3 }, { label: "David", value: 4 }, { label: "Kerry", value: 5 }, { label: "Tom", value: 6 }];
const testPassedPersons = [3, 5, 6];
const res = [...persons].sort((a,b) => {
const indexA = testPassedPersons.indexOf(a.value)
const indexB = testPassedPersons.indexOf(b.value)
if (indexA === -1 && indexB === -1) return 0;
if (indexA === -1) return 1
if (indexB === -1) return -1
return indexA - indexB
//or ternary operator
//return (indexA === -1 && indexB === -1) ? 0 : (indexA === -1) ? 1 : (indexB === -1) ? -1 : indexA - indexB
})
console.log(res)
.as-console-wrapper { max-height: 100% !important; top: 0; }
使用2个过滤器的实现将为[3, 5, 6, 2]
而不是Michelle,Kerry,Tom,Mary
提供Mary,Michelle,Kerry,Tom
。如果这是你想要的结果,你可以使用reduce
在1个循环而不是2个过滤器(2个循环)中实现它。此外,将传递的person数组转换为集合可以帮助实现O(1)查找
const persons = [ { label: "jhon", value: 1 }, { label: "Mary", value: 2 }, { label: "Michelle", value: 3 }, { label: "David", value: 4 }, { label: "Kerry", value: 5 }, { label: "Tom", value: 6 }];
const testPassedPersons = [3, 5, 6, 2];
const testPassedPersonsSet = new Set(testPassedPersons)
const {passed,notPassed} = persons.reduce((acc,{label,value}) => {
acc[testPassedPersonsSet.has(value) ? 'passed' : 'notPassed'].push({label,value})
return acc
},{passed:[],notPassed:[]})
console.log([...passed,...notPassed])
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以简单地使用Array.splice()
方法和Array.unshift()
方法来实现这一点。
Live Demo:
const persons = [
{
label: "jhon",
value: 1
},
{
label: "Mary",
value: 2
},
{
label: "Michelle",
value: 3
},
{
label: "David",
value: 4
},
{
label: "Kerry",
value: 5
},
{
label: "Tom",
value: 6
}
];
const testPassedPersons = [3, 5, 6];
persons.forEach((obj, index) => {
if (testPassedPersons.includes(obj.value)) {
persons.splice(index, 1);
persons.unshift(obj);
}
});
console.log(persons)