I've found some good answers about how getting an index of an array with indexOf. However, this doesn't suit me since I must return the the index of the parent array that contains a child array which contains an object with certain id.
This would be a sample array:
[
[{id: 1}],
[{id: 2}],
[
{id: 3}
{id: 4}
],
[
{id: 5},
{id: 6}
],
[{id: 7}],
]
For example, if I'd like to find the index of the id : 4 the index would be 2.
I've thought about a map inside the findIndex method:
array.findIndex((el) => el.map((e) => e.id === noteId )));
But have not found much success yet.
As Andy Ray commented, a map doesnt return a true value.
so the correct way to do it is this:
array.findIndex((el) => el.some((e) => e.id === noteId )));
const array = [
[{id: 1}],
[{id: 2}],
[
{id: 3},
{id: 4},
],
[
{id: 5},
{id: 6}
],
[{id: 7}],
]
const noteId = 3;
console.log(array.findIndex((el) => el.some((e) => e.id === noteId )));
Related
const my_arr = [
{id: 1, arr: [{subId: 1, value: 1}],
{id: 2, arr: [{subId: 2, value: 2}],
{id: 3, arr: [{subId: 3, value: 1}],
]
how do I map over this array my_arr and then map over arr to return an array like so:
[
{subId: 1, value: 1},
{subId: 3, value: 1},
]
basically filtering out only where values are 1 and then returning only that sub object
I've tried doing
my_arr.map((x) => x.map((y) => y.value === 1 ? y : null))
You can try this approach with flatMap and filter
const my_arr = [
{id: 1, arr: [{subId: 1, value: 1}]},
{id: 2, arr: [{subId: 2, value: 2}]},
{id: 3, arr: [{subId: 3, value: 1}]},
]
const result = my_arr.flatMap(item => item.arr).filter(item => item.value === 1)
console.log(result)
Your current approach maps over the outer array my_arr, and then uses an inner map to map over the inner array. Since .map() always returns an array, you'll end up mapping your objects from your outer array to other arrays, which you don't want. You can instead use .flatMap() which will combine/join the returned inner arrays into one array. However, rather than using .map() as your inner method though, you should use .filter() to create an array of objects that have a value of 1, which then gets merged into your resulting outer array created by the .flatMap() method:
const my_arr = [ {id: 1, arr: [{subId: 1, value: 1}]}, {id: 2, arr: [{subId: 2, value: 2}]}, {id: 3, arr: [{subId: 3, value: 1}]}, ];
const res = my_arr.flatMap(({arr}) => arr.filter(({value}) => value === 1));
console.log(res);
Since you are dealing with nested structure, you will have to get little creative.
First you will have to filter the array.
Inside it, you can use .some to check if your condition matches and return matching
Now you have the filtered list but you still need to format your output. You can use .reduce and concat arr of every item
This will be useful if you have multiple items in arr.
const my_arr = [
{id: 1, arr: [{subId: 1, value: 1}] },
{id: 2, arr: [{subId: 2, value: 2}] },
{id: 3, arr: [{subId: 3, value: 1}] },
]
const output = my_arr
.filter(({ arr }) =>
arr.some(({value}) => value === 1)
).reduce((acc, { arr }) => acc.concat(arr), [])
console.log(output)
Is it possible in some way to filter let's say such an array of object arrays:
[[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]]
To get array of objects which all arrays have the same property (id), so in this case it output will be:
[{id: 2}] // becasue this id is the same in all three subarrays
I've only try intersectionBy from loadash but it seems to work in completely other way :/
I would take one array (it's enough to take one because if the property is not there its already not common), in this example I'm taking the first one but probably more efficient will be picking the shortest one.
iterate over the array and check for each object if its common to all other arrays.
const arr = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]];
let firstArray = arr.shift();
const result = firstArray.reduce((common, item)=>{
if (arr.every(inner => inner.some(_item => _item.id === item.id))) {
common.push(item);
}
return common;
},[])
console.log(result);
Using Ramda:
const input = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]];
R.intersection(...input);
You can use array reduce,forEach , findIndex and sort to get the most common object. In first inside the reduce callback use forEach to iterate each of the child array and then use findIndex to find if in accumulator array , there exist an object with same id. If it does not exist create a new object with key id & occurrence. If it exist then increase the value of occurrence. This will give the most common id, even if an id is not present in few child array
let data = [
[{id: 1}, {id: 2}, { id: 3}],
[{id: 6}, {id: 2}],
[{id: 2}, {id: 1}, {id: 9}, { id: 3}]
];
let obj = data.reduce((acc, curr) => {
curr.forEach((item) => {
let getInd = acc.findIndex((elem) => {
return elem.id === item.id
});
if (getInd === -1) {
acc.push({
id: item.id,
occurence: 1
})
} else {
acc[getInd].occurence += 1;
}
})
return acc;
}, []).sort((a, b) => {
return b.occurence - a.occurence;
});
console.log(obj[0])
var arr = [
[{id: 1}, {id: 2}, {id: 3}],
[{id:6}, {id: 2}],
[{id: 2}, {id: 1}, {id: 9}, {id: 3}]
]
var obj = {};
var arrLength = arr.length;
arr.forEach((val,index) => {
val.forEach((item) =>{
if(index == 0){
if(!obj.hasOwnProperty(item.id)){
obj[item.id] = 1;
}
}else{
if(obj.hasOwnProperty(item.id)){
obj[item.id] = obj[item.id] + 1;
}else{
return;
}
}
});
});
var output = [];
for (const property in obj) {
if(obj[property] == arrLength){
output.push({
id: property
})
}
}
console.log(output);
My approach is similar to that of naortor, but with an attempt to be more generic.
const intersection = (pred) => (as, bs) =>
as .filter (a => bs .some (b => pred (a, b)))
const intersectionAll = (pred) => (xs) =>
xs.length ? xs .reduce (intersection (pred)) : []
const input = [[{id: 1}, {id: 2}, {id: 3}], [{id:6}, {id: 2}], [{id: 2}, {id: 1}, {id: 9}, {id: 3}]]
const eqIds = (a, b) => a .id == b .id
console .log (
intersectionAll (eqIds) (input)
)
.as-console-wrapper {min-height: 100% !important}
This version requires you to say how you identify two equal values. (We will check that they have the same id, but any binary predicate function is allowed.) This function is passed to intersection which returns a function that takes two arrays and finds all the element in common between those two. intersectionAll wraps this behavior up, folding intersection over an array of arrays.
This breakdown is useful, as intersection is a useful function on its own too. And abstracting out the id check into a function you need to supply means these functions are much more generic.
I am trying to use array.filter() to compare two arrays and separate out values that the two arrays have in common, based on a certain property (id), vs. values they don't have in common. The common ids I want to push to a new array (recordsToUpdate). And I want to push the remaining elements from arr2 to a new array (recordsToInsert).
What I've tried is not working. How can I rework this to get the results I wanted? - (which in the example here should be one array of 1 common element {id: 3}, and another array of the remaining elements from arr2):
const arr1 = [{id: 1}, {id: 2}, {id: 3}];
const arr2 = [{id: 3}, {id: 4}, {id: 5}];
let recordsToUpdate = [];
let recordsToInsert = [];
recordsToUpdate = arr1.filter(e => (arr1.id === arr2.id));
recordsToInsert = ?
console.log('recordsToUpdate: ', recordsToUpdate);
console.log('recordsToInsert: ', recordsToInsert);
The desired result should be:
recordsToUpdate = [{id: 3}];
recordsToInsert = [{id: 4}, {id: 5}];
Try this, which uses Array.prototype.find to test for whether an object exists in arr2 with a given id:
const arr1 = [{id: 1}, {id: 2}, {id: 3}];
const arr2 = [{id: 3}, {id: 4}, {id: 5}];
const recordsToUpdate = arr1.filter(e => arr2.find(obj => obj.id === e.id) !== undefined);
const recordsToInsert = arr1.filter(e => arr2.find(obj => obj.id === e.id) === undefined);
console.log('recordsToUpdate: ', recordsToUpdate);
console.log('recordsToInsert: ', recordsToInsert);
Update to Robin post using some instead of find. It is just other way around.
const arr1 = [{id: 1}, {id: 2}, {id: 3}];
const arr2 = [{id: 3}, {id: 4}, {id: 5}];
const recordsToUpdate = arr1.filter(e => arr2.some(obj => obj.id === e.id));
const recordsToInsert = arr2.filter(e => !arr1.some(obj => obj.id === e.id));
console.log('recordsToUpdate: ', recordsToUpdate);
console.log('recordsToInsert: ', recordsToInsert);
I think this is what you are after... I added values to show the replacement. If you are doing any kind of state management, be careful as I am directly mutating the current array.
const arr1 = [
{ id: 1, v: "a" },
{ id: 2, v: "b" },
{ id: 3, v: "old" }
];
const arr2 = [
{ id: 3, v: "new" },
{ id: 4, v: "e" },
{ id: 5, v: "f" }
];
function updateRecords(currentArray, updatesArray) {
const currentIds = currentArray.map(item => item.id);
updatesArray.forEach(updateItem =>
currentIds.includes(updateItem.id)
? (currentArray[
currentIds.findIndex(id => id === updateItem.id)
] = updateItem)
: currentArray.push(updateItem)
);
return currentArray;
}
console.log(updateRecords(arr1, arr2))
This now gives the option below:
[
{
"id": 1,
"v": "a"
},
{
"id": 2,
"v": "b"
},
{
"id": 3,
"v": "new"
},
{
"id": 4,
"v": "e"
},
{
"id": 5,
"v": "f"
}
]
Putting it in a function is also something you likely want to do as you will likely use this multiple places in your code.
Suppose I have this array of object:
let arr =
[
{ id: "1"},
{ id: "2"},
{ id: "3"}
]
I would create a list of arrays, so I tried:
arr.map(x => x.id);
but this will return:
["1", "2", "3"]
I want an array for each value, eg: ["1"] ["2"] ["3"]
If you want an array of each then do
arr.map(x=>[x.id]);
try this
arr.map(x => [x.id]);
Note that if you want to get an array with all the object values, you can use Object.values(). This will work for object with one key and for objects with multiple keys.
let arr =
[
{id: "1", foo:"bar"},
{id: "2"},
{id: "3"}
];
console.log(arr.map(x => Object.values(x)));
Other useful cases could be:
1) Get an array with the keys for each object => Object.keys()
let arr =
[
{id: "1", foo:"bar"},
{id: "2"},
{id: "3"}
];
console.log(arr.map(x => Object.keys(x)));
2) Get an array with the pairs of [key, value] (entries) for each object => Object.entries()
let arr =
[
{id: "1", foo:"bar"},
{id: "2"},
{id: "3"}
];
console.log(arr.map(x => Object.entries(x)));
I have an array, which contains array of objects. I need to extract the property value "id" of items that have objects.
Example of array:
let myArray = [
[ {id: "1"}, {id: "2"} ],
[],
[],
[ {id: "3"} ]
]
How can I extract and create an array like this:
["1", "2", "3"]
I tried this:
tagIds = myArray.map(id =>{id})
You can use reduce to flatten the array and use map to loop thru the array and return the id.
let myArray = [
[{id: "1"}, {id: "2"}],
[],
[],
[{id: "3"}],
];
let result = myArray.reduce((c, v) => c.concat(v), []).map(o => o.id);
console.log(result);
Another way with simple nested loops:
let myArray = [
[ {id: "1"}, {id: "2"} ],
[],
[],
[ {id: "3"} ]
]
//----------------------------------
let newArray=[];
for (let i=0;i<myArray.length;i++){
for (let j=0;j<myArray[i].length;j++){
newArray.push(myArray[i][j].id);
}
}
console.log(newArray); //outputs ['1','2','3']
You can use .concat() to create array of single objects and then .map() to extract ids:
let myArray = [
[{id: "1"}, {id: "2"}], [], [], [{id:"3"}]
];
let result = [].concat(...myArray).map(({ id }) => id);
console.log(result);
Docs:
Array.prototype.concat()
Array.prototype.map()
Spread Syntax
Here is my solution:
let a = myArray.flat(100) // you can put (3) or (10) in here, the higher the flatter the array
let b = a.map(
function(value){
return parseInt(value.id)
}
)
console.log(b)
You can also write a recursive function to make this work with any number of arrays, for example:
function extractIds(arr) {
return arr.reduce((a, item) => {
if (Array.isArray(item)) {
return [
...a,
...extractIds(item)
];
}
return [
...a,
item.id
];
}, [])
}
extractIds([{id: 1}, [{id: 2}], {id: 3}, [{id: 4}, [{id: 5}, [{id: 6}]]]])
the return of extractIds will be [1, 2, 3, 4, 5, 6].
Notice that without the recursive part you would end up with something like this: [1, 2, [3, {id: 4}, [{id: 5}]]] (Not exactly like this, but just as an example).