Creating new array and removing unwanted objects from old arrays javascipt - javascript

I have 2 arrays containing objects, I want to create a new array without "duplicates". The problem is that the two arrays are not identical and I want to choose based on id.
This is a simple version of what I got:
let array1 = [
{
"id": "1",
"type": "abc"
},
{
"id": "2",
"type": "one, two, three"
}
]
let array2 = [
{
"id": "1",
"type": "abc",
"country": "England"
},
{
"id": "3",
"type": "one, two, three",
"country": "Germany"
}
]
let array3 = array1.filter(x => array2.forEach(y => x.id === y.id)).concat(array2);
The result I want for array3 is:
{
"id": "1",
"type": "abc"
}
In this particular case country is not important and will be thrown away anyway.
How do I filter out unwanted objects and create a new array with only the objects I want?

If you are looking for an intersection between the arrays the shortest answer is to use the filter with a find.
let array1 = [{
id: '1',
type: 'abc',
},
{
id: '2',
type: 'one, two, three',
},
];
let array2 = [{
id: '1',
type: 'abc',
country: 'England',
},
{
id: '3',
type: 'one, two, three',
country: 'Germany',
},
];
const array3 = array1.filter(value => array2.find((a)=>a.id==value.id));
console.log(array3);

let array1 = [{
id: '1',
type: 'abc',
},
{
id: '2',
type: 'one, two, three',
},
];
let array2 = [{
id: '1',
type: 'abc',
country: 'England',
},
{
id: '3',
type: 'one, two, three',
country: 'Germany',
},
];
array2.forEach((el, idx) => {
const match = array1.find((el2) => el2.id === el.id);
if (!match) array1.push(el);
});
console.log(array1);
Something like this ? I assumed from your explanation that you want to merge array2 with array1.
You will end up with the unique objects from array2 having the extra country property, if you want to delete that you need an extra step before pushing.

I think this is what you were trying to achieve:
let array1 = [ { "id": "1", "type": "abc" }, { "id": "2", "type": "one, two, three" } ];
let array2 = [ { "id": "1", "type": "abc", "country": "England" }, { "id": "3", "type": "one, two, three", "country": "Germany" } ];
let array3 = array1.filter(x => array2.map(y => y.id).includes(x.id));
console.log( array3 );
In order to avoid have to recompute the array2 array of ids you can get them in advance as follows:
let array1 = [ { "id": "1", "type": "abc" }, { "id": "2", "type": "one, two, three" } ];
let array2 = [ { "id": "1", "type": "abc", "country": "England" }, { "id": "3", "type": "one, two, three", "country": "Germany" } ];
const ids = array2.map(({id}) => id);
let array3 = array1.filter(x => ids.includes(x.id));
console.log( array3 );

Related

how to get array from object with index as one of the object property

I have an object
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
Need to filter this from below array, with array index as object.key
const myFilter = [123,789];
Code I am trying is as below but it returning array inedx as 0,1,2... but I need the index to be object.key.
let selectedItems = myFilter.map((key) => {
return items[key];
});
Current output :
[0:{
key: 123,
name: "one name"
}, 1: {
key: 789,
name: "three name"
}]
Expected Output
[123:{
key: 123,
name: "one name"
}, 789: {
key: 789,
name: "three name"
}]
jsfiddle - https://jsfiddle.net/kb374exh/2/
Your actual output is actually correct and the only possible result from mapping the myFilter array to the matching properties from items.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = myFilter.map((key) => items[key]);
console.log(selectedItems);
The logged output you see is including the array index. You likely are seeing the index included when logging in the browser.
If you want an array of objects where the original key is the new index then the best you can likely do is an array of length <highest key> and a bunch of "holes" that are simply undefined.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.entries(items).reduce((selectedItems, [key, value]) => {
if (myFilter.includes(value.key)) selectedItems[key] = value;
return selectedItems;
}, []);
console.log(selectedItems);
If you are ok with the result being an object then you can have more succinct output, you'll basically end up with back with an object with key-value pairs filtered out.
const items = {
"123": {
"key": 123,
"name": "one name",
},
"456": {
"key": 456,
"name": "two name",
},
"789": {
"key": 789,
"name": "three name",
},
};
const myFilter = [123, 789];
const selectedItems = Object.fromEntries(Object.entries(items).filter(([, value]) => myFilter.includes(value.key)));
console.log(selectedItems);

Add objects from within JSON array into JavaScript array with keys remapped

I have the following json returned from an ajax request
[
{
"id": "1",
"task": "eat pizza",
"username": "all"
},
{
"id": "2",
"task": "drink soda",
"username": "all"
}
]
I am trying to add specific pieces of data from the json to an existing js array.
this.$todoData2 = [
{
'id': '5',
'text': 'Cheese',
'done': false
},
]
I need to add json key id and its matching value - example: "id": key,
I need to add json key task as text with its matching value - example: "text": key
I need to add a "done": "false" to set so a final result would look like:
this.$todoData2 = [
{
"id": "1",
"text": "eat pizza",
'done': false
}
{
"id": "2",
"text": "drink soda",
'done': false
}
{
'id': '5',
'text': 'Cheese',
'done': false
},
]
I have no examples of what I have tried as I am not sure where to even begin with this. Keep in mind that json may contain a lot more results.
Use .forEach() to iterate over the 'updates' Array, while destructuring the key / value pairs you want to use
Create your object, then .push() it to the Array
const $todoData2 = [
{'id': '5', 'text': 'Cheese', 'done': false},
];
const update = [
{"id": "1", "task": "eat pizza", "username": "all"},
{"id": "2", "task": "drink soda", "username": "all"}
];
update.forEach(({id, task}) => {
$todoData2.push({
'id': id,
'text': task,
'done': false
});
});
console.log($todoData2);
You can merge both arrays and then use map.
let arr = [
{
"id": "1",
"task": "eat pizza",
"username": "all"
},
{
"id": "2",
"task": "drink soda",
"username": "all"
}
]
let todoData2 = [
{
'id': '5',
'text': 'Cheese',
'done': false
},
]
todoData2 = todoData2.concat(arr).map( obj => ({ id:obj.id, text:obj.task || obj.text , done:false }) );
console.log(todoData2)
If the point here is to simply append and rename keys, it may by done as simple as that:
const newItems = [{"id":"1","task":"eat pizza","username":"all"},{"id":"2","task":"drink soda","username":"all"}],
existingItems = [{"id":"5","text":"Cheese","done":false}]
existingItems.push(...newItems.map(({id,task:text}) => ({id,text,done:false})))
console.log(existingItems)
.as-console-wrapper{min-height:100%}

How to get difference between two array of object with different property comparer?

I have these two arrays:
main:
[
{ id: "1"},
{ id: "2"},
{ id: "3"}
]
filtered:
[
{ id: "80", link_id: "1"},
{ id: "50", link_id: null},
{ id: "67", link_id: "3"}
]
I need to get the items of main which have as id those contained in filtered with the property: link_id, I tried with:
main.filter(x => filtered.includes(x.id));
the problem is that this will return null, and also this doesn't allow me to check if link_id is null
var main = [{
id: "1"
},
{
id: "2"
},
{
id: "3"
}
],
filtered = [{
id: "80",
link_id: "1"
},
{
id: "50",
link_id: null
},
{
id: "67",
link_id: "3"
}
],
result = main.filter(x =>
filtered.includes(x.id)
);
console.log(result)
Try with some() method
var main = [
{ id: "1"},
{ id: "2"},
{ id: "3"}
]
var filtered = [
{ id: "80", link_id: "1"},
{ id: "50", link_id: null},
{ id: "67", link_id: "3"}
]
console.log(main.filter(x => filtered.some(item => item.link_id === x.id) ));
you are close, basically you need to check in each item of the filtered array.
includes is more for a plain object as the documentation states.
check the snippet below, you can use findIndex, find or some to get if the element exist on the filtered array.
const main = [{
id: "1"
},
{
id: "2"
},
{
id: "3"
}
]
const filtered = [{
id: "80",
link_id: "1"
},
{
id: "50",
link_id: null
},
{
id: "67",
link_id: "3"
}
]
const resultFindIndex = main.filter(item => -1 !== filtered.findIndex(filteredItem => item.id === filteredItem.link_id))
const resultFind = main.filter(item => filtered.find(filteredItem => item.id === filteredItem.link_id))
const resultSome = main.filter(item => filtered.some(filteredItem => item.id === filteredItem.link_id))
console.log(resultFindIndex)
console.log(resultFind)
console.log(resultSome)

How to merge multiple object arrays into one array cross with sub array?

I have two arrays of objects:
1)
[
{
"userId": 9
},
{
"userId": 14
}
]
2)
[{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
I would like to merge two arrays as follows:
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
I tried to use let however I couldn't find the way to manipulate switch the subarray :
let arr1 = [{"userId": 9}, {"userId": 14}];
let arr2 = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}];
let result = arr1.map(o => Object.assign(o, ...arr2));
console.log(result);
return result;
The result I got with the previous implementation is like this :
[{"userId":9,"role":"1","group":"2"},{"userId":14,"role":"1","group":"2"}]
However, I would like to get the result as follows :
[
{"userId":9,"role":"1","group":"2"},
{"userId":14,"role":"1","group":"2"}
{"userId":9,"role":"1","group":"3"},
{"userId":14,"role":"1","group":"3"}
]
var a = [{
"userId": 9
},
{
"userId": 14
}
]
var b = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}]
console.log(
b.map(z=>a.map(x=>({...x, ...z}))).flat()
)
Another solution using for loop
let arr1 = [{ "userId": 9 }, { "userId": 14 }]
let arr2 = [{"role": "1","group": "3"}, {"role": "1","group": "2" }]
let result = [];
for (let group of arr2) {
for (let user of arr1) [
result.push(Object.assign({}, group, user))
]
}
console.log(JSON.stringify(result))
//output is:
// [
// {"role":"1","group":"3","userId":9},
// {"role":"1","group":"3","userId":14},
// {"role":"1","group":"2","userId":9},
// {"role":"1","group":"2","userId":14}
// ]
Stackblitz example
To achieve expected result, use below option of looping through two arrays
var x = [
{
"userId": 9
},
{
"userId": 14
}
]
var y = [{"role": "1", "group": "3"}, {"role": "1", "group": "2"}]
let result = []
y.forEach((v, i) =>{
x.forEach((y,i) => result.push({...v, ...y}))
})
console.log(result);
codepen - https://codepen.io/nagasai/pen/pxvzOG?editors=1010
You could iterate over the two arrays like this and push the merged values into result:
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
Which could also be written in ONE LINE:
arr1.forEach(e => arr2.forEach(e2 => result.push(Object.assign({}, e, e2))));
const arr1 = [{
"userId": 9
},
{
"userId": 14
}
];
const arr2 = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
const result = [];
arr1.forEach(e => {
arr2.forEach(e2 => {
result.push(Object.assign({}, e, e2));
});
});
console.log(result);
You can use a mix a reduce and map to boil it down to a single array of objects.
let data = [{
"userId": 9
},
{
"userId": 14
}
]
let metaData = [{
"role": "1",
"group": "3"
}, {
"role": "1",
"group": "2"
}];
let dataReducer = data.reduce((acc, curr) => {
let metadataReducer = metaData.map((val) => {
return {
...curr,
...val
};
}, []);
return [...acc, ...metadataReducer];
}, []);
console.log(dataReducer)
Here a short approach for an arbitrary count of arrays of objects.
var array1 = [{ userId: 9 }, { userId: 14 }],
array2 = [{ role: "1", group: "3" }, { role: "1", group: "2" }],
result = [array1, array2]
.reduce((a, b) =>
a.reduce((r, v) =>
r.concat(b.map(w => Object.assign({}, v, w))), []));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You're basically asking for a Cartesian product of the two arrays. flatMap is a useful function here. For each element of one array, merge it with all objects from the other array, then return a flat result.
const a = [{userId: 9}, {userId: 14}];
const b = [{role: "1", group: "3"}, {role: "1", group: "2"}];
const merged = b.flatMap(ae => a.map(be => ({...be, ...ae})));
console.log(merged);

Create multiple object looping over array

So i have an array which stores hobbies for each user in an array within the object..
var hobbies = [
{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
]
What i want to return is a new array of objects but each hobby separated into their own object like below.
var result = [
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
What is have so far is
hobbies.filter((f, i) => f.hobbies.length > 0).map((p, i) => {
while (i < p.hobbies.length) {
return { id : p.id, hobby : p.hobbies[i] };
}
});
which only returns
[
{
"id": 2,
"hobby": "football"
},
{
"id": 3,
"hobby": "basketball"
}
]
You can use array#reduce with array#map. Iterate through each object and then iterate through each hobby of hobbies and create the object.
var hobbies = [ { "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ],
result = hobbies.reduce((r, {id, hobbies}) => r.concat(hobbies.map(hobby => ({id, hobby}))), []);
console.log(result);
I know, "functional" programming is considered "cool" around these parts, however, have you considered using simple loops to, well, loop over your data?
let result = [];
for (let {hobbies, id} of data)
for (let hobby of hobbies)
result.push({id, hobby})
In my opinion, this is far more readable than any reduce spaghetti one could come up with ;)
You need to use inner-loop to loop through the hobbies and push them one-by-one to the target array:
var hobbies = [{
"id": 1,
"hobbies": []
},
{
"id": 2,
"hobbies": [
"football"
]
},
{
"id": 3,
"hobbies": [
"football",
"basketball"
]
}
];
var result = hobbies.reduce((acc, item) => {
item.hobbies.forEach(hobby => {
acc.push({
id: item.id,
hobby: hobby
});
});
return acc;
}, []);
console.log(result);
You can use array.prototype.reduce:
var hobbies = [{"id": 1,"hobbies": []},{"id": 2,"hobbies": ["football"]},{"id": 3, "hobbies": ["football","basketball"]}];
var res = hobbies.reduce((m, o) => (o.hobbies.forEach(h => m.push({id: o.id, hobby: h})), m), []);
console.log(res);
You need nested loops and this is the basics of it:
You first need to loop over the main hobbies array.
Then for each item in the array (which represents a person), you want to loop through their hobbies, and for each one of those hobbies, you need to push an object made up of the profile ID and the hobby into results array I created earlier.
var hobbies = [{ "id": 1, "hobbies": [] }, { "id": 2, "hobbies": [ "football" ] }, { "id": 3, "hobbies": [ "football", "basketball" ] } ];
let result = [];
hobbies.forEach(function(profile){
profile.hobbies.forEach(function(hobby){
result.push(
{
"id": profile.id,
"hobby": hobby
}
);
});
});
console.log(result)
Update: the other answers with Array.reduce (a more specialised loop) will cut the above code down even further.

Categories