I have a big datasource with objects. What I wanted to do is, for each new value for each key, getting the object to the top of the array. Everytime, for each key, that I find a new value, I wanted the object to go up that datsource. So that the topmost x elements would be the x different values the properties can have. So given:
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}
I would get
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}
Above is just a dummy example, since I don't always know its keys, quantity or names. What I am currently doing is going through all the objects and its keys to find the new values for each key. Doing so, saving this value into an array of uniques and taking the current object to the top of my array. Repeating this process for each object with unique key value going to the second position, third, and so on. Since I don't always know its keys, quantity or names, I try to do this dynamically.
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;
}
However it seems to get stucking trying to read undefined values. I tried checking for emptiness of datasource, current key value or event current object but it does not change. It gets into an undefined or empty field and it breaks. I don't know what I'm doing wrong here.
One way forward would be to 'group by' the name first, then iterate the longest group and access each other grouped array by index.
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);
Or as a more generic function accepting a callback to access the property/ies to group by and an optional sort function to sort the grouped arrays by before mapping to the result
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