I'm trying to use lodash to compare two arrays of objects and return the difference between the two, then adding it to the original data set. Reason being, the new data will contain the same data from the original. For example, I have 3 objects in orgData, and when I request newData, it will contain the same orgData plus one more object.
var orgData = [{
"id": 1000,
"title": "First item"
}, {
"id": 1001,
"title": "Second item"
}];
var newData = [{
"id": 1000,
"title": "First item"
}, {
"id": 1001,
"title": "Second item"
}, {
"id": 1002,
"title": "Third item"
}];
My only delimiter in comparing is the id which is unique. I've tried the following, but the error I receive is 'Cannot read property of 'id' undefined' which makes sense.
_.filter(orgData, function(o, x) {
return o.id !== newData[x].id;
}).forEach(function(x) {
orgData.push(x);
});
Keep track of ids in a separate data structure:
var orgDataIds = [];
_.each(orgData, function(value) {
orgDataIds.push(value.id);
})
Inspect the id of each object in newData, and add the object to orgData when the corresponding id isn't found in the ids array:
_.each(newData, function(value) {
var id = value.id;
if (orgDataIds.indexOf(id) === -1) {
orgDataIds.push(id);
orgData.push(value);
}
})
It's not clear to me when you want to remove objects from an array though. Are you intending to take the intersection of the two arrays?
var orgData = [{
"id": 1000,
"title": "First item"
}, {
"id": 1001,
"title": "Second item"
}];
var newData = [{
"id": 1000,
"title": "First item"
}, {
"id": 1001,
"title": "Second item"
}, {
"id": 1002,
"title": "Third item"
},
{
"id": 1003,
"title": "Forth item"
}];
var newArray = _.union(orgData,newDate)
console.log(JSON.stringify(newArray))
// this will return union of this two array
Related
I'm trying to filter some objects based on another array of objects. So I'm getting data from an API. These are for example receipts:
[
{
"id": 1,
"name": "test",
"category": {
"id": 1,
"name": "Cookies",
},
},
{
"id": 2,
"name": "test2",
"category": {
"id": 2,
"name": "Candy",
},
}
]
Then I'm trying to filter the objects on the category name based on another array of categories.
I've created a function for this:
function onSelectCategory(category) {
let receiptsList = receipts.filter((a) =>
a.category.includes(category.name)
);
setReceiptsView(receiptsList);
setSelectedCategory(category);
}
const category = [ { "id": 2, "name": "Candy" } ];
onSelectCategory(category);
When I run this function, I get an empty Array []. I can't really figure out what I'm doing wrong.
Since the param seems to be an array of objects, you need to use Array#some for comparison instead:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const receiptsList = receipts.filter(({ category }) =>
categories.some(({ name }) => name === category.name)
);
console.log(receiptsList);
Another solution using Set:
const receipts = [
{ "id": 1, "name": "test", "category": { "id": 1, "name": "Cookies" } },
{ "id": 2, "name": "test2", "category": { "id": 2, "name": "Candy" } }
];
const categories = [ { "id": 2, "name": "Candy" } ];
const categorySet = new Set(categories.map(({ name }) => name));
const receiptsList = receipts.filter(({ category }) =>
categorySet.has(category.name)
);
console.log(receiptsList);
Assuming that category (the parameter) is a string, the issue is that you are attempting to get the attribute name from the string, when you should be comparing the string to the object.
Try this:
a.category.name == category;
instead of
a.category.includes(category.name)
I may be wrong aboout assuming that category is a string, please clarify by telling us what the parameter category is equal to.
I have a JSON in the following format and need to convert the 2 values into a Key / Value pair in javascript
"column_values": [
{
"id": "status",
"text": "Working on it"
}
]
I need the result to be
"column_values"[{"status": "Working on it"}]
I need the code to iterate through the column_values array and convert all the sets of id and text pairs to the key = id value : Value = text:values
Is my result possible?
Additional Information...
I am parsing a response from monday.com api in zapier.
the api payload is contained in
const results = response.json;
the full api payload is
{
"data": {
"boards": [
{
"name": "Test Board",
"items": [
{
"name": "Name Change",
"id": "625495642",
"column_values": [
{
"id": "person",
"text": ""
},
{
"id": "subitems",
"text": "Subitem 1, Subitem 2"
},
{
"id": "status",
"text": "Working on it"
},
{
"id": "dropdown",
"text": "Test1"
},
{
"id": "formula",
"text": ""
}
]
}
]
}
]
},
"account_id": 1111
}
I need to the the code to parse the data and replace the column_values with the format above, and then pass the reformated payload to
return results;
You just Map the Array you start out with to an Array with the values.
var column_values = [ { "id": "status", "text": "Working on it" } ]
var KeyValuePairs = column_values.map(cv => [cv.id,cv.text]);
console.log(KeyValuePairs);
If every object is going to contain the id and text keys only, you can map it and delete the other keys.
column_values = column_values.map(item => {
item[item.id] = item.text;
delete item.id;
delete item.text;
return item;
});
try this
var column_values = [ { "id": "status", "text": "Working on it" } ]
var res = column_values.map(x => ({[x.id] : x.text}))
console.log(res)
I have object like this:
{
"id": 1,
"name": "first",
"sections": [
{
"id": 1,
"title": "First section",
"contents": [
{
"id": "123",
"title": "Sample title 1",
"description": "<html>code</html>",
},
{
"id": "124",
"title": "Sample title 2",
"description": "<html>code</html>"
},
{
"id": "125",
"title": "Some other sample",
"description": "<html>code</html>"
}
]
},
{
"id": 2,
"title": "Second section",
"contents": [
{
"id": "126",
"title": "Sample title 126",
"description": "<html>code</html>"
},
{
"id": "127",
"title": "Sample title 127",
"description": "<html>code</html>"
}
]
}
]
}
I want to remove specific object from contents array by its id (all those ids are unique).
I can easily find element I want to remove, but I'm unable to find in which section this element is to splice it later.
obj.sections.forEach(function(section) {
section.contents.forEach((content) => {
if (content.id == 125) {
console.log(content)
console.log(section)
}
})
})
In above code console.log(sections) returns undefined. How can I get position in sections array which contains contents array that has specific id. For example, id: 125 would return sections position 0, so I can use splice to remove that element.
If my approach is completely wrong please point me in right direction, thanks :)
You could use .filter() instead of .splice(). .filter() will keep all items which you return true for and discard of those which you return false for. So, if the current section's content's object has an id equal to the one you want to remove you can return false to remove it, otherwise return true to keep that item. You can use this with .map() to map each section object to a new one with an updated contents array:
const obj = { "id": 1, "name": "first", "sections": [ { "id": 1, "title": "First section", "contents": [ { "id": "123", "title": "Sample title 1", "description": "<html>code</html>", }, { "id": "124", "title": "Sample title 2", "description": "<html>code</html>" }, { "id": "125", "title": "Some other sample", "description": "<html>code</html>" } ] }, { "id": 2, "title": "Second section", "contents": [ { "id": "126", "title": "Sample title 126", "description": "<html>code</html>" }, { "id": "127", "title": "Sample title 127", "description": "<html>code</html>" } ] } ] };
const idToRemove = 125;
obj.sections = obj.sections.map(
sec => ({...sec, contents: sec.contents.filter(({id}) => id != idToRemove)})
);
console.log(obj);
.as-console-wrapper { max-height: 100% !important; top: 0; } /* ignore */
Why not use a simple filter for accomplishing the task. Also, it will be much cleaner and immutable way of doing it.
let newArrWithoutContentWithGivenId = obj.sections.map(section =>
({...section, contents: section.contents.filter(content =>
content.id != 125)}));
Here, we are mapping each section whose content does not contain the ID 125. In short, section > content.id != 125 will be removed from the new array.
Hope it helps :)
Note: Code is not tested, it is just to help you find a way to do it cleanly.
You only need to use the second argument of forEach :)
obj.sections.forEach(function(section, sectionIndex) {
section.contents.forEach((content, contentIndex) => {
if (content.id == 125) {
// use the sectionIndex and contentIndex to remove
}
})
})
I have an object like this:
var data = [
{"id":"36e1e015d703120058c92cf65e6103eb","title":"Alex McGibbon"},
{"id":"60beb5e7d7600200e5982cf65e6103ad","title":"Alex Linde"},
{"subs":[{"id":"62826bf03710200044e0bfc8bcbe5df1","title":"Abel Tuter"}],"id":"63e8479fdb161300bde15901cf96191c","title":"Abdul Waheed"},
{"subs":[{"subs":[{"id":"12826bf03710200044e0bfc8bcbe5db1","title":"Alfonso Griglen"},{"subs":[{"id":"06826bf03710200044e0bfc8bcbe5d8a","title":"Allyson Gillispie"},{"id":"b282abf03710200044e0bfc8bcbe5d28","title":"Allan Schwantd"}],"id":"22826bf03710200044e0bfc8bcbe5dec","title":"Alejandra Prenatt"}],"id":"0a826bf03710200044e0bfc8bcbe5d7a","title":"Adela Cervantsz"},{"id":"4847c4d4d773020058c92cf65e61038e","title":"Alisa Chinoy"},{"id":"71826bf03710200044e0bfc8bcbe5d3b","title":"Aileen Mottern "},{"id":"a8f98bb0eb32010045e1a5115206fe3a","title":"Abraham Lincoln"}],"id":"7c2e6109dbd65300bde15901cf9619b5","title":"Raju Koyagura"}
];
console.log(data)
Now I want to retrieve all the id values as a new array without consideration of which nested level it is.
My expected result is something like this::
var result = ['36e1e015d703120058c92cf65e6103eb','60beb5e7d7600200e5982cf65e6103ad','62826bf03710200044e0bfc8bcbe5df1','06826bf03710200044e0bfc8bcbe5d8a','b282abf03710200044e0bfc8bcbe5d28','22826bf03710200044e0bfc8bcbe5dec','0a826bf03710200044e0bfc8bcbe5d7a','4847c4d4d773020058c92cf65e61038e','71826bf03710200044e0bfc8bcbe5d3b','a8f98bb0eb32010045e1a5115206fe3a','7c2e6109dbd65300bde15901cf9619b5'];
console.log(result);
I am not getting any idea how to achieve it.?
You can use JSON.stringify to walk on the tree easily:
const ids = [];
JSON.stringify(data, (key, value) => {
if (key === 'id') ids.push(value);
return value;
});
Create a recursive function and check if that object have a key by id. Push the value of id. If the key is another array then call the same function with new value
var data = [{
"id": "36e1e015d703120058c92cf65e6103eb",
"title": "Alex McGibbon"
},
{
"id": "60beb5e7d7600200e5982cf65e6103ad",
"title": "Alex Linde"
},
{
"subs": [{
"id": "62826bf03710200044e0bfc8bcbe5df1",
"title": "Abel Tuter"
}],
"id": "63e8479fdb161300bde15901cf96191c",
"title": "Abdul Waheed"
},
{
"subs": [{
"subs": [{
"id": "12826bf03710200044e0bfc8bcbe5db1",
"title": "Alfonso Griglen"
}, {
"subs": [{
"id": "06826bf03710200044e0bfc8bcbe5d8a",
"title": "Allyson Gillispie"
}, {
"id": "b282abf03710200044e0bfc8bcbe5d28",
"title": "Allan Schwantd"
}],
"id": "22826bf03710200044e0bfc8bcbe5dec",
"title": "Alejandra Prenatt"
}],
"id": "0a826bf03710200044e0bfc8bcbe5d7a",
"title": "Adela Cervantsz"
}, {
"id": "4847c4d4d773020058c92cf65e61038e",
"title": "Alisa Chinoy"
}, {
"id": "71826bf03710200044e0bfc8bcbe5d3b",
"title": "Aileen Mottern "
}, {
"id": "a8f98bb0eb32010045e1a5115206fe3a",
"title": "Abraham Lincoln"
}],
"id": "7c2e6109dbd65300bde15901cf9619b5",
"title": "Raju Koyagura"
}
];
let newArray = [];
function getAllId(arr, key) {
arr.forEach(function(item) {
for (let keys in item) {
if (keys === key) {
newArray.push(item[key])
} else if (Array.isArray(item[keys])) {
getAllId(item[keys], key)
}
}
})
}
getAllId(data, 'id')
console.log(newArray)
I am trying to get a list together from an array but some of the fields are null and it seems to be breaking there and returning:
obj.names is null
Here is the code:
My Code
var data = {
"people": [{
"id": "32",
"description": "some description",
"archived": "",
"new": 0,
"names": [{
"name": "name 1",
"translations": null
}, {
"name": "name 2",
"translations": null
}],
}, {
"id": "56",
"description": "some description",
"archived": "",
"new": 0,
"names": [{
"name": "name 3",
"translations": null
}, {
"name": "name 4",
"translations": null
}],
}, {
"id": "99",
"description": "some description",
"archived": "",
"new": 0,
"names": null,
},
]
};
var mainData = [data];
var namesList = [];
for (var i = 0; i < mainData[0].people.length; i++) {
var obj = mainData[0].people[i];
var nme = obj.names.name;
namesList.push(nme);
}
console.log(namesList); //This should have the list of names
<div id="container"></div>
JSFiddle Link
How can I fix this?
names is an array, you need to get the name property from the objects inside the names array.
Replace these lines
var nme = obj.names.name;
namesList.push(nme);
by
if( obj.names )
{
var nme = obj.names.map( function(item){
return item.name;
});
namesList = namesList.concat(nme);
}
map method is used to iterate the array and return the name property of each array item.
I prefer using array methods like map/reduce/forEach.
You end up with something like this:
// we want to loop over the people array, but it's not a 1-to-1 relation, since we want all name in the names array, so we use reduce into new array.
var namesList = data.people.reduce(function( ary, peopleRecord ) {
// We want to concat the names from the names array to our result
return ary.concat(
// but if the names array is null, we have nothing to concat, so check if the names array exists
peopleRecord.names && peopleRecord.names.map(function( nameRecord ) {
return nameRecord.name;
// Or else if the names array doesn't exist, just concat an empty array to the final result.
}) || []
);
}, []);