I need to create a new array as you can see it has a key value that specifies the latitude and longitude.
I want the key values that are equal to be set as 1 only but according to who has the highest count
[
{
"color":"green",
"coment_calification":"Califica",
"count":7,
"key":"-13.0711552&-76.3723776&Califica",
"latitud":"-13.0711552",
"longitud":"-76.3723776"
},
{
"color":"yellow",
"coment_calification":"Reporte",
"count":6,
"key":"-13.0711552&-76.3723776&Reporte",
"latitud":"-13.0711552",
"longitud":"-76.3723776"
},
{
"color":"green",
"coment_calification":"Califica",
"count":1,
"key":"-13.1711552&-76.3423776&Califica",
"latitud":"-13.1711552",
"longitud":"-76.3423776"
},
{
"color":"yellow",
"coment_calification":"Reporte",
"count":2,
"key":"-13.1711552&-76.3423776&Reporte",
"latitud":"-13.1711552",
"longitud":"-76.3423776"
}
]
let result = count.filter((e) => e && e.count && e.key == e.key);
let datas = result;
Is this what you're looking for?
const result = arr.reduce((acc, cur) => {
const matchIndex = acc.findIndex(saved =>
saved.latitud === cur.latitud
&& saved.longitud === cur.longitud
);
if (matchIndex !== -1) {
if (cur.count > acc[matchIndex].count) {
acc.splice(matchIndex, 1, cur);
}
return acc;
}
return [...acc, cur];
}, []);
It looks like the array contains objects that differ mostly by their count props but have several other duplicate props. I think I understand the OP to want to remove these almost-duplicates retaining the one with the highest count.
One way to do this is to sort the array to be descending by count, walk through them, pushing onto a result only those that aren't already in the result.
The only thing not super clear in the OP is what constitutes sameness besides the count field. Here, we guess that the coment_calification key being the same means the objects are to be treated as duplicate.
const objects = [
{
"color":"green",
"coment_calification":"Califica",
"count":7,
"key":"-13.0711552&-76.3723776&Califica",
"latitud":"-13.0711552",
"longitud":"-76.3723776"
},
{
"color":"yellow",
"coment_calification":"Reporte",
"count":6,
"key":"-13.0711552&-76.3723776&Reporte",
"latitud":"-13.0711552",
"longitud":"-76.3723776"
},
{
"color":"green",
"coment_calification":"Califica",
"count":1,
"key":"-13.1711552&-76.3423776&Califica",
"latitud":"-13.1711552",
"longitud":"-76.3423776"
},
{
"color":"yellow",
"coment_calification":"Reporte",
"count":2,
"key":"-13.1711552&-76.3423776&Reporte",
"latitud":"-13.1711552",
"longitud":"-76.3423776"
}
];
objects.sort((a,b) => b.count-a.count) // sort descending
const result = [];
for (let object of objects) {
// supposing matching coment_calification props means a match
let alreadyInResult = result.find(r => r.coment_calification === object.coment_calification)
if (!alreadyInResult) result.push(object);
}
console.log(result)
I have an array of objects that looks like below
var FinalArray = [
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"789"},"name":"hello","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"}];
I am trying to loop through the array and return an array of items group by the key "name" which will hold indexes of the items with same key.
expected result like below:
[
{bene: [0,2]},
{leg: [1,3]},
{hello: [4]}
]
I've put together the below but can't get it to work.
var obj = FinalArray.reduce(function(agg, item, index, f) {
var name = item.name || ""
var index = FinalArray.findIndex(item)
/* var copy = [...item.jArray];
*/ if (!agg[name]) {
agg[name] = []
}
agg[name].push(index)
return agg;
}, {})
fairly new to using reduce and groupby. any help is appreciated. Thanks
You can generate an object of the names with their indexes with a reduce on the original array, just pushing indexes into the array for each name.
If you then want an array of those values (I'm not sure this is a better structure), you can use Object.entries to get the key value pairs and map those into individual objects in an array
var FinalArray = [
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"789"},"name":"hello","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"}];
var obj = FinalArray.reduce((acc, { name }, i) => {
acc[name] = (acc[name] || []).concat([i])
return acc
}, {})
console.log(obj)
objArray = Object.entries(obj).map(([k, v]) => ({ [k] : v }))
console.log(objArray)
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can achieve this by just using two JavaScript methods Array.forEach() along with Object.keys().
Live Demo :
// Input array
var FinalArray = [
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"789"},"name":"hello","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"}
];
const resObj = {};
const output = [];
// creating a object with the required key: values.
FinalArray.forEach((obj, index) => {
resObj[obj.name] ? resObj[obj.name].push(index) : resObj[obj.name] = [index];
});
// destructuring the object into an array of objects.
Object.keys(resObj).forEach(key => {
output.push({
[key]: resObj[key]
})
});
// final output
console.log(output);
The OP might try a combination of ...
a reduce based approach which straightforwardly creates and collects an index/map of name based groups where the group key resemble an iterated item's name key, and the group value is an array of same name-value item-indices.
and a mapping of the reduced object's entries.
const finalArray = [
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"789"},"name":"hello","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
];
console.log(
'index/map based result ...',
finalArray
.reduce((groups, { name }, idx) => {
(groups[name] ??= []).push(idx);
return groups;
}, {})
);
console.log(
"OP's expected result ...",
Object
.entries(
finalArray
.reduce((groups, { name }, idx) => {
(groups[name] ??= []).push(idx);
return groups;
}, {})
)
.map(([key, value]) => ({ [ key ]: value }))
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Another approach was to solely stick to reduce, where one then needs to implement a reducer function which achieves everything in a single run and does both ...
keeping track of the (to be) generated groups and the (to be) collected indices
and aggregating the final result of the reduce method's accumulator/collector object which gets passed as the method's 2nd parameter ... its initialValue.
const finalArray = [
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"123"},"name":"bene","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"B"}],"Ref":{"docId":"456"},"name":"leg","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
{"jArray":[{"Cd":"A"}],"Ref":{"docId":"789"},"name":"hello","check1":false,"check2":false,"check3":false,"check4":false,"id":"0001"},
];
const { result } = finalArray
.reduce(({ result = [], groups = {} }, { name }, idx) => {
let group = groups[name];
if (!group) {
group = groups[name] = { [ name ]: [] };
result.push(group);
}
group[name].push(idx)
return { result, groups };
}, { result: [] });
console.log({ result });
.as-console-wrapper { min-height: 100%!important; top: 0; }
I have an Array of objects and one object
const filterArray = [{bestTimeToVisit: 'Before 10am'}, {bestDayToVisit: Monday}]
This values are setting in a reducer and the payload will be like
{bestTimeToVisit: 'After 10am'}
or
{bestDayToVisit: Tuesday}.
So what I need is when I get a payload {bestTimeToVisit: 'After 10am'} and if bestTimeToVisit not in filterList array, then add this value to the filterList array.
And if bestTimeToVisit already in the array with different value, then replace the value of that object with same key
if(filterArray.hasOwnProperty("bestTimeToVisit")) {
filterArray["bestTimeToVisit"] = payload["bestTimeToVisit"];
} else {
filterArray.push({"bestTimeToVisit": payload["bestTimeToVisit"]});
}
I convert the object array into a regular object and then back into an object array. makes things less complicated. I'm making the assumption each object coming back only has one key/value and that order doesnt matter.
const objectArraytoObject = (arr) =>
arr.reduce((acc, item) => {
const key = [Object.keys(item)[0]];
return { ...acc, [key]: item[key] };
}, {});
const newValues = [{ someKey: 'something' }, { bestDayToVisit: 'Tuesday' }];
const filterArray = [
{ bestTimeToVisit: 'Before 10am' },
{ bestDayToVisit: 'Monday' },
];
const newValuesObj = objectArraytoObject(newValues);
const filterObj = objectArraytoObject(filterArray);
const combined = { ...filterObj, ...newValuesObj };
const combinedToArray = Object.keys(combined).map((key) => ({
[key]: combined[key],
}));
console.log(combinedToArray);
Need to iterate over the array and find objects that satisfy for modification or addition if none are found.
function checkReduced(filterrray,valueToCheck="After 10am"){
let isNotFound =true;
for(let timeItem of filterrray) {
if(timeItem.bestTimeToVisit && timeItem.bestTimeToVisit !== valueToCheck) {
timeItem.bestTimeToVisit=valueToCheck;
isNotFound=false;
break;
}
}
if(isNotFound){filterrray.push({bestTimeToVisit:valueToCheck})}
}
const filterArray = [{bestDayToVisit: "Monday"}];
checkReduced(filterArray,"After 9am");//calling the function
const updateOrAdd = (arr, newItem) => {
// get the new item key
const newItemKey = Object.keys(newItem)[0];
// get the object have the same key
const find = arr.find(item => Object.keys(item).includes(newItemKey));
if(find) { // the find object is a reference type
find[newItemKey] = newItem[newItemKey]; // update the value
} else {
arr.push(newItem); // push new item if there is no object have the same key
}
return arr;
}
// tests
updateOrAdd([{ a: 1 }], { b: 2 }) // => [{ a: 1 }, { b: 2 }]
updateOrAdd([{ a: 1 }], { a: 2 }) // => [{ a: 2 }]
I have an object that has multiple arrays that looks something like this.
let obj = {
links: ["https://somelink.com/image.jpg", "https://somelink.com/image2.jpg"],
IDs: ["yCmj", "4q1K"],
}
I want to make it so that it's turned into an array of objects. Like the following.
let newObj = {
templates: [
{id:"yCmj", link: "https://somelink.com/image.jpg"},
{id:"4q1K", link: "https://somelink.com/image2.jpg"}
]
}
What I have tried:
I tried mapping the object values to a new array but the second map overwrites the whole array.
let templates = obj.templateIDs.map((id) => ({id}))
templates = obj.thumbnailLinks.map((thumbnailLink) => ({thumbnailLink}))
let newObj = templates
The easiest way to accomplish this would be to pick either obj.links or obj.IDs and map their values to an object and use the index to locate the corresponding parallel value.
const obj = {
links: ["https://somelink.com/image.jpg", "https://somelink.com/image2.jpg"],
IDs: ["yCmj", "4q1K"],
};
const newObj = {
templates: obj.links.map((link, index) => (id => ({ id, link }))(obj.IDs[index]))
};
console.log(newObj);
.as-console-wrapper { top: 0; max-height: 100% !important; }
This operation is typically called "zipping" 2 arrays:
const zip = (a,b, zipper) => {
if(a.length != b.length)
throw "arrays must be the same length";
return a.map( (v,i) => zipper(v,b[i]))
}
const obj = {
links: ["https://somelink.com/image.jpg", "https://somelink.com/image2.jpg"],
IDs: ["yCmj", "4q1K"],
}
const newObj = {
templates: zip(obj.links, obj.IDs, (link,id) => ({link,id}))
}
console.log(newObj);
You can simply use map.
const obj = {
links: ["https://somelink.com/image.jpg", "https://somelink.com/image2.jpg"],
IDs: ["yCmj", "4q1K"],
};
const newObj = {
templates: obj.links.map((link, i) => ({ link, id: obj.IDs[i] })),
};
console.log(newObj);
let obj = {
links: ["https://somelink.com/image.jpg", "https://somelink.com/image2.jpg","https://somelink.com/image2.jpg"],
IDs: ["yCmj", "4q1K","34er"],
}
let propsKey = Object.keys(obj)
let finalArr = obj.links.map( ()=> {
return {}
})
propsKey.forEach( (prop) => {
obj[prop].forEach( (v,i)=>finalArr[i][prop] = v )
})
console.log(finalArr)