How to add new value inside array of object by id (not new item) - javascript

I'm trying add a new value inside my array by id. I'm not trying add a new item in my array... For this I can use push(), but it add new item not a new value.
I'm trying do it:
My array:
const data =
[
{
"id": 1,
"year":2019,
"value": 2,
},
{
"id": 2,
"year": 2019,
"value": 89,
},
{
"id": 3,
"year": 2019,
"value": 99,
}
]
Inside an especific id I would to add a new value like this:
data.forEach(item => {
if(item.id === 2){
//data inside id 2 -> item: 55
}
})
So my new dataarray looks like this:
const data =
[
{
"id": 1,
"year":2019,
"value": 2,
},
{
"id": 2,
"year": 2019,
"value": 89,
"item": 55
},
{
"id": 3,
"year": 2019,
"value": 99,
}
]
In most of my searches, I found just how to add a new element. But this I know how to do (push()).
So how to add a new value inside specified id?

Just assign the property you want to add:
data.forEach(item => {
if(item.id === 2){
item.item = 55;
}
})
If the IDs are unique, you can use the .find() method:
var el = data.find(item => item.id === 2);
if (el) {
el.item = 55;
}

try
data.find(x=> x.id==2).item=55;
const data =
[
{
"id": 1,
"year":2019,
"value": 2,
},
{
"id": 2,
"year": 2019,
"value": 89,
},
{
"id": 3,
"year": 2019,
"value": 99,
}
]
data.find(x=>x.id==2).item=55;
console.log(data);

You can iterate and assign value based on your criteria
data.map(function(x){
if(x.id == 2){
x.value = 100;
}
})

You can implement method using Array.find to avoid unnecessary iterations:
const array = [
{
"id": 1,
"year":2019,
"value": 2,
},
{
"id": 2,
"year": 2019,
"value": 89,
},
{
"id": 3,
"year": 2019,
"value": 99,
}
];
const changeValue = (array, id, field, value) =>
array.find(el => el.id === id)[field] = value;
changeValue(array, 1, 'year', 9999);
console.log('result: ', array);

You have an array of objects and you want to add a field to one of the objects. So, first, you have to find the object you want to change. Array items can be accessed by index, but you don't know the index. There are several methods to find an item in an array.
var item = data.find(function(d, i){
return item.id === 2; //criteria
});
or in ES6 syntax:
var item = data.find(d=>d.id == 2);
after that, you can change item the way you want.
item.anotherField = 'another value';
As you said, push() adds an item to the array. It doesn't change existing items in the array.

Your code is more or less right there. To set the property of an item, you can do either object.propertyName = ... or object["propertyName"] = ....
With that, you'd simply need to update your example to look like this:
data.forEach(item => {
if(item.id === 2){
item.item = 55; //data inside id 2 -> item: 55
}
})
As a more efficient alternative, consider Array.find(). It won't continue to loop through the array after it finds the id, whereas your forEach will always loop through the array in its entirety.
const data = [ { "id": 1, "year":2019, "value": 2, }, { "id": 2, "year": 2019, "value": 89, }, { "id": 3, "year": 2019, "value": 99, } ];
( data.find(({id})=> id === 2) || {} ).item = 55;
console.log(data);
You'll notice I've followed the .find() with || {}. This is simply so that if an item with id === 2 isn't found, attempting to set the property won't throw an error.

Related

Unable to get blank properties and it's id from array of object

i want to get empty properties(only need to check role,group and subgroup) and it's id both in array of objects.
let tempdata = [
{
"id": 41,
"tool": "Artifactory",
"role": "",
"group": "Dish",
"subgroup": "Ehub test 009",
"subscriptionId": "artifactory-ehub-test-009"
},
{
"id": 4,
"tool": "Gitlab",
"role": "Owner",
"group": "IDP",
"subgroup": "IDP-Service-Templates",
"subscriptionId": "gitlab-51663585"
}
]
What i tried so far is this:
tempdata.filter(item=>item.group=='' || item.subgroup=='' || item.role=='').map(item=>item.id)
but this only gives my id [41] what i want is [{"id":41,"blank_properties":["role"]}]
Can somebody please help.
you can simply do it this way
tempdata.map((item)=>{
let d = [];
if(item.role === ''){
d.push('role')
}
if(item.group ===''){
d.push('group')
}
if(item.subgroup===''){
d.push('subgroup')
}
return {...item,'blank_prop':d}
})
tempdata.filter(item=>item.group=='' || item.subgroup=='' ||
item.role=='').map(item=>{
let temp=[];
if(item.group==='')temp.push('group')
if(item.role==='')temp.push('role')
if(item.subgroup==='')temp.push('subgroup')
if(item.subscriptionId==='')temp.push('subscriptionId')
if(item.tool==='')temp.push('tool')
return {id:item.id,blank_property:temp};})
I'm going to propose a more sophisticated solution, in case you're interested in additional ways to approach this problem:
let tempData =
[
{
"id": 41,
"tool": "Artifactory",
"role": "",
"group": "Dish",
"subgroup": "Ehub test 009",
"subscriptionId": "artifactory-ehub-test-009"
},
{
"id": 4,
"tool": "Gitlab",
"role": "Owner",
"group": "IDP",
"subgroup": "IDP-Service-Templates",
"subscriptionId": "gitlab-51663585"
},
];
// An array of all properties you want to check for blank strings
const propertiesToCheck = [ "group", "subgroup", "role" ];
result = tempData
.filter((item) =>
{
// Your original code was filtering the array of objects to
// JUST ones that have at least one of those properties set to ""
// So this filter does the same thing.
//
// If you DON'T actually want to outright remove ones that don't match this condition,
// then you can just remove this entire filter step.
// Iterate object keys and values
for (const [ key, value ] of Object.entries(item))
{
// If the key is not in the above array of propertiesToCheck,
// then skip it
if (propertiesToCheck.indexOf(key) == -1)
{
continue;
}
// If we encounter one of those properties and it's blank, return true
if (value == "")
{
return true;
}
}
// Return false if we get through all of the properties without encountering one that's blank
return false;
})
.map((item) =>
{
// Create an object to house the result in the manner you described
const result =
{
id: item.id,
blank_properties: [],
};
// Iterate the object keys and values again
for (const [ key, value ] of Object.entries(item))
{
// Same deal as before
if (propertiesToCheck.indexOf(key) == -1)
{
continue;
}
// Then, if the value is blank...
if (value == "")
{
// ...push its key to the blank_properties array
result.blank_properties.push(key);
}
}
// Return the result!
return result;
});
// Prints:
// [ { id: 41, blank_properties: [ 'role' ] } ]
console.log(result);

Javascript - Get occurence of json array with ESLINT 6

I can't set up an algo that counts my occurrences while respecting ESlint's 6 standards in javascript.
My input table is :
[
{
"id": 2,
"name": "Health",
"color": "0190fe"
},
{
"id": 3,
"name": "Agriculture",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
},
{
"id": 1,
"name": "Urban planning",
"color": "0190fe"
}
]
And i want to get :
{"Urban planning": 2, "Health": 1, ...}
But that does not work with ESLINT / REACT compilation...
This is my code :
const jsonToIterate = *'MyPreviousInputJson'*
const names = []
jsonToIterate.map(item => (names.push(item.name)))
const count = []
names.forEach(item => {
if (count[item]){
count.push({text: item, value: 1})
} else {
count.forEach(function(top){top.text === item ? top.value =+ 1 : null})
}
})
Thank you so much
Well, you want an object in the end, not an array, so count should be {}. I also wouldn't use map if you're not actually returning anything from the call. You can use reduce for this:
let counts = topicsSort.reduce((p, c, i, a) => {
if (!p.hasOwnProperty(c.name)) p[c.name] = 0;
p[c.name]++;
return p;
}, {});
I'm half exppecting someone to close this as a duplicate because all you've asked for is a frequency counter. But here's an answer anyway:
const jsonToIterate = *'MyPreviousInputJson'*;
const names = {};
jsonToIterate.map(obj => {
if(obj.name in names){
names[obj.name]++
}
else{
names[obj.name] = 1;
}
})

Sort by the sum of array in object

I am looking for a solution to sort an array by the sum of an array property within an object.
For example if the main array is
[
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
},
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
}
]
How can I sort the sum of Day to return as
[
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
},
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
}
]
You just need sort your array with comparator, that uses reduce to calc sum of inner array values:
let arr = [{"Grid": {"Day": [11,12]}, "Name": "One"},
{"Grid": {"Day": [5,2]}, "Name": "Two"},
{"Grid": {"Day": [1,2]}, "Name": "Two"}];
let sum = el => el.Grid.Day.reduce((a,b) => a + b);
arr.sort((a,b) => sum(a) - sum(b));
console.log(arr)
You can use a combination of reduce to sum the array, and sort to order the output:
var input = [
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
},
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
}
];
var result = input.sort( (a,b) => sumOfDay(a) - sumOfDay(b));
console.log(result);
function sumOfDay(obj){
return obj.Grid.Day.reduce( (acc,curr) => acc + curr, 0);
}
Note that Array.prototype.sort actually mutates the original array in place. so the above could also do
input.sort( (a,b) => sumOfDay(a) - sumOfDay(b));
console.log(input);
So, don't fall into the trap of thinking the original array is unchanged just because I assigned the result to result!.
If you do wish to sort a copy of the array do this:
var result = input.slice().sort( (a,b) => sumOfDay(a) - sumOfDay(b));
Create a new Array of a by mapping through it and using reduce on the Day Array of Grid to get your sum which you can compare within a sort to return your list sorted by summed days.
const a = [
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
},
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
}
]
const daySum = ({Grid}) => Grid.Day.reduce((prev, curr) => prev+curr, 0)
const sorted = [...a].sort(daySum)
console.log(sorted)
console.log(a) //Original array intact
Just "another" approach to solve the issue: assuming you (someday, later, eventually) may need to sort again, a good approach may also be to add a property to each grid item holding the sum of the days, avoiding the .reduce call every time you need to sort the array.
In this approach, .forEach is used to create the new property (through .reduce), and then .sort is used to sort the array in-place.
const input = [
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
},
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
}
];
// Add a DaySum property evaluating the sum of the days.
input.forEach(i => i.Grid.DaySum = i.Grid.Day.reduce((a,b) => a + b));
// ^--- the second parameter (initial value) is unneeded here due to the fact that all elements are actually numeric, hence if the initial value is the first element of the array, which is a number already.
// Sor the array by that property.
input.sort((a,b) => a.Grid.DaySum - b.Grid.DaySum);
console.log(input);
Or, as suggested by #Andreas below, you can directly assign the property while sorting:
const input = [
{
"Grid": {
"Day": [
11,
12
]
},
"Name": "One"
},
{
"Grid": {
"Day": [
5,
2
]
},
"Name": "Two"
}
];
const sum = (a,b) => a + b;
input.sort((a,b) => {
a.Grid.DaySum = a.Grid.DaySum || a.Grid.Day.reduce(sum);
b.Grid.DaySum = b.Grid.DaySum || b.Grid.Day.reduce(sum);
return a.Grid.DaySum - b.Grid.DaySum;
});
console.log(input);

Javascript underscore data format array of object

By using underscoreJS lib and manipulating some datas, i have this object
var data = {
"2017-09-26": [
{
"id": 274281,
"value": 10
},
{
"id": 274282,
"value": 20
}],
"2017-09-27": [
{
"id": 274281,
"value": 12
},
{
"id": 274282,
"value": 13
}],
}
i would like to obtain this result below by passing the keys as date in the child object and transform the value of id key as the new key of the value of value
var data = [{
date:"2017-09-26",
274281: 10,
274282: 20
},
{
date:"2017-09-27",
274281: 12,
274282: 13
}]
Please does someone as an idea to help me to do this and ideally efficiently?
Thanks
Here it is in one line:
Object.keys(data).map(key => ({date: key, ...data[key].reduce((p, c) => {p[c.id] = c.value; return p}, {})}))
Result:
[{
"274281":10,
"274282":20,
"date":"2017-09-26"
},
{
"274281":12,
"274282":13,
"date":"2017-09-27"
}]
You need nested loops. The first level creates the objects with the date property, then you loop over the objects in that value, and add the id: value properties to the result.
var newdata = _.map(data, (date, objects) => {
res = {date: date};
_.each(objects, obj => {
res[obj.id] = obj.value;
});
return res;
});
You can use Array.from() on the result of Object.entries(data) to create an array of objects by passing a callback function as the second argument.
Then for each sub-array, use .reduce() to create a new object from its members.
var data = {
"2017-09-26": [
{ "id": 274281, "value": 10 },
{ "id": 274282, "value": 20 }
],
"2017-09-27": [
{ "id": 274281, "value": 12 },
{ "id": 274282, "value": 13 }
],
};
const result = Array.from(Object.entries(data), ([key, arr]) =>
arr.reduce((res, {id, value}) =>
Object.assign(res, {[id]: value})
, {date: key})
);
console.log(result);
Here's one that's just about the same, but uses the new object literal spread syntax.
var data = {
"2017-09-26": [
{ "id": 274281, "value": 10 },
{ "id": 274282, "value": 20 }
],
"2017-09-27": [
{ "id": 274281, "value": 12 },
{ "id": 274282, "value": 13 }
],
};
const result = Array.from(Object.entries(data), ([key, arr]) =>
({date: key,
...Object.assign({}, ...arr.map(({id, value}) => ({[id]: value})))
})
);
console.log(result);

convert integer to array of object.

var items = [
{ "id": 1, "label": "Item1" },
{ "id": 2, "label": "Item2" },
{ "id": 3, "label": "Item3" }
];
I have this array of objects named 'items'. I get itemselected = 3 from the database.
I need to convert this 3 into the following form.
0:Object
id:3
label:"Item3"
Similarly, if i have a value 2 coming from the database, i should convert it to
0:Object
id:2
label:"Item2"
Can anyone please let me hint of how to get it solved. i am not here to get the answer. These questions are quite tricky for me and i always fail to get the logic right. Any advice on how to master this conversions will be of great help. thanks.
Since you tagged underscore.js, this should be very easy:
var selectedObject = _.findWhere(items, {id: itemselected});
Using ECMA6, you can achieve the same using .find method on arrays:
let selectedObject = items.find(el => el.id === itemselected);
With ECMA5, you can use filter method of arrays. Be careful that filter returns undefined if no element has been found:
var selectedObject = items.filter(function(el) { return el.id === itemselected});
Use jquery $.map function as below
$.map(item, function( n, i ) { if(n["id"] == 3) return ( n );});
Based on the title of your question: «convert integer to array of object». You can use JavaScript Array#filter.
The filter() method creates a new array with all elements that
pass the test implemented by the provided function.
Something like this:
var items = [{
"id": 1,
"label": "Item1"
},
{
"id": 2,
"label": "Item2"
},
{
"id": 3,
"label": "Item3"
}
];
var value = 2;
var result = items.filter(function(x) {
return x.id === value;
});
console.log(result); // Prints an Array of object.
Try this
var obj = {} ;
items = [
{ "id": 1, "label": "Item1" },
{ "id": 2, "label": "Item2" },
{ "id": 3, "label": "Item3" }
];
items.map(function(n) { obj[n.id] = n });

Categories

Resources