我有一个大的对象数据源。我想做的是,对于每个键的每个新值,把对象放到数组的顶部。每次,对于每个键,我找到一个新值,我都希望对象向上到数据源。所以最上面的x个元素就是x个不同的属性值。鉴于:
arr[0] = {name: john, age: 14, adress: xxx}
arr[1] = {name: john, age: 14, adress: xxx}
arr[2] = {name: marie, age: 14, adress: xxx}
arr[3] = {name: marie, age: 14, adress: xxx}
arr[4] = {name: john, age: 15, adress: xxx}
我将得到
arr[0] = {name: john, age: 14, adress: xxx}
arr[1] = {name: marie, age: 14, adress: xxx}
arr[2] = {name: john, age: 15, adress: xxx}
arr[3] = {name: marie, age: 14, adress: xxx}
arr[4] = {name: john, age: 14, adress: xxx}
上面的只是一个假的例子,因为我并不总是知道它的键、数量或名称。我现在做的是遍历所有的对象和它的键,为每个键找到新的值。这样做,将这个值保存到一个唯一数组中,并将当前对象置于数组的顶部。对每个具有唯一键值的对象重复此过程,将键值移到第二个位置、第三个位置,依此类推。由于我并不总是知道它的键、数量或名称,所以我尝试动态地执行此操作。
filterDS(dataSource){
let uniqueColumns;
let i = 0;
let j = 0;
let temp;
dataSource.forEach(data => {
let keys = Object.keys(data);
keys.forEach( key => {
console.log(key + ":" + data[key]);
uniqueColumns[key].push(data[key]);
temp = dataSource[i];
j = dataSource.indexOf(data);
dataSource[i] = dataSource[j];
dataSource[j] = temp;
i++
})
});
return dataSource;
}
然而,它似乎卡住试图读取未定义的值。我尝试检查数据源,当前键值或事件当前对象的空白,但它没有改变。它进入一个未定义或空字段,然后中断。我不知道我哪里做错了。
一种方法是先按名称分组,然后迭代最长的组,并通过索引访问其他分组数组。
const arr = [{ name: 'john', age: 14, adress: 'xxx' }, { name: 'john', age: 14, adress: 'xxx' }, { name: 'marie', age: 14, adress: 'xxx' }, { name: 'marie', age: 14, adress: 'xxx' }, { name: 'john', age: 15, adress: 'xxx' }, { name: 'tim', age: 15, adress: 'xxx' },];
// 'group by' object.name
const tempMap = {};
for (const o of arr) {
(tempMap[o.name] ??= []).push(o);
}
const groups = Object.values(tempMap);
// get the length of the longest grouped array
const maxLen = Math.max(...groups.map(o => o.length))
const result = [];
// iterate the longest array accessing each grouped array by index
for (let i = 0; i < maxLen; i++) {
for (const arr of groups) {
if (i < arr.length) {
result.push(arr[i]);
}
}
}
console.log(result);
或者作为一个更通用的函数,接受一个回调来访问要进行分组的属性/ies和一个可选的sort函数,在映射到结果
之前对分组数组进行排序。
function filterDS(dataSource, getProp, sortFn) {
// use the passed callback to 'group-by'
const tempMap = {};
for (const o of dataSource) {
(tempMap[getProp(o)] ??= []).push(o);
}
const groups = Object.values(tempMap);
// sort if a sortFn has been passed
if (typeof sortFn === 'function') {
groups.sort(sortFn);
}
// get the length of the longest grouped array
const maxLen = Math.max(...groups.map(o => o.length))
const result = [];
// iterate the longest array accessing each grouped array by index
for (let i = 0; i < maxLen; i++) {
for (const arr of groups) {
if (i < arr.length) {
result.push(arr[i]);
}
}
}
return result
}
const arr = [{ name: 'beth', age: 14, adress: 'xxx' }, { name: 'andrew', age: 14, adress: 'xxx' }, { name: 'carrie', age: 14, adress: 'xxx' }, { name: 'xeno', age: 15, adress: 'xxx' }, { name: 'carrie', age: 14, adress: 'xxx' }, { name: 'andrew', age: 15, adress: 'xxx' }, { name: 'andrew', age: 15, adress: 'xxx' },];
console.log(filterDS(arr, (o) => o.name, (a, b) => a[0].name.localeCompare(b[0].name))); // sorted alphabetical asc.
console.log(filterDS(arr, (o) => o.name)); // not sorted