Intersection of two arrays in javascript - javascript

I want to search in a big array for different id from another array and print all intersections of those two arrays
I want to map through my bigTable and I want to create another array of correspondence, each found element must contain all fields+tableName+tableID like this :
const output = [{
ID: 1234,
title: 'title1',
TableName: 'loramIpsum',
TableId: 11,
},
{
ID: 98523,
title: 'mylasttitle',
TableName: 'table2',
TableId: 87545,
},
{
ID: 97766,
title: 'mylastdata',
TableName: 'table2',
TableId: 87545,
},
]
I've create a function but I think there is another best and sample solution, this is my function :
const getResult = (wantedData, bigArray) => {
return wantedData.flatMap((id) =>
bigArray.flatMap((family) =>
family.Tables.flatMap((table) => {
let item = table.myDatas.find((el) => el.ID === id);
if (item) {
item.Table = table.TableName;
item.familyId = family.GridId;
return item;
}
}).filter((result) => result !== undefined)
)
);
};
console.log(getResult(wantedData, bigArray))
<script>
const wantedData = [1235, 98523, 97766];
const bigArray = [{
bigArrayId: 1111,
Tables: [{
TableId: 11,
TableName: 'loramIpsum',
myDatas: [{
ID: 1234,
title: 'title1',
},
{
ID: 1235,
title: 'title2',
},
],
}, ],
},
{
bigArrayId: 674665,
Tables: [{
TableId: 87545,
TableName: 'table2',
myDatas: [{
ID: 98523,
title: 'mylasttitle',
},
{
ID: 24134,
title: 'alex',
},
{
ID: 97766,
title: 'mylastdata',
},
],
}, ],
},
];
</script>
Any help please ? Can I do it with recursive function ?

I think you need to solve this problem in two steps:
First, create a flat array of tables
Then filter the array by conditions
const bigArray=[{bigArrayId:1111,Tables:[{TableId:11,TableName:"loramIpsum",myDatas:[{ID:1234,title:"title1"},{ID:1235,title:"title2"}]}]},{bigArrayId:674665,Tables:[{TableId:87545,TableName:"table2",myDatas:[{ID:98523,title:"mylasttitle"},{ID:24134,title:"alex"},{ID:97766,title:"mylastdata"}]}]}];
const wantedData = [1235, 98523, 97766];
const flatTables = bigArray.flatMap(({ Tables }) =>
Tables.flatMap(({ myDatas, TableId, TableName }) =>
myDatas.map((data) => ({ ...data, TableId, TableName })) ));
const result = flatTables.filter(({ ID }) => wantedData.includes(ID));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

I think if you do it something like this you'll be able to map after you've found the right things rather than mapping everything and then filtering that result:
const bigArray = [{ bigArrayId: 1111, Tables: [{ TableId: 11, TableName: 'loramIpsum', myDatas: [{ ID: 1234, title: 'title1', }, { ID: 1235, title: 'title2', }, ], }, ], }, { bigArrayId: 674665, Tables: [{ TableId: 87545, TableName: 'table2', myDatas: [{ ID: 98523, title: 'mylasttitle', }, { ID: 24134, title: 'alex', }, { ID: 97766, title: 'mylastdata', }, ], }, ], }, ];
const wantedData = [1235, 98523, 97766];
const wanted_set = new Set(wantedData);
const push_concat = (arr1, arr2) => {
for(let i = 0; i < arr2.length; i++)
arr1.push(arr2[i]);
return arr1;
};
const res = bigArray.reduce(
(acc, { Tables }) =>
push_concat(acc,
Tables.flatMap(({ TableId, TableName, myDatas }) =>
myDatas
.filter(({ ID }) => wanted_set.has(ID))
.map(({ ID, title }) => ({ ID, title, TableId, TableName }))
)
),
[]
);
console.log(res);

Related

assign incremental index to nested array of object?

How to assign incremental index to nested array of object below? each members will have a property 1,2,3,4
groupMembersByTitle = [{
members: [{
id: 'uuid'
}, {
id: 'uuid'
}]
}, {
members: [{
id: 'uuid'
}, {
id: 'uuid'
}]
}]
I'm stuck here
const r = groupMembersByTitle.map(o => ({
...o,
members: o.members.map((o2, index) => ({
...o2,
no: ++index
}))
}))
You'll need a more persistent outer variable.
const groupMembersByTitle = [{
members: [{
id: 'uuid'
}, {
id: 'uuid'
}]
}, {
members: [{
id: 'uuid'
}, {
id: 'uuid'
}]
}];
let no = 1;
const mapped = groupMembersByTitle.map(
obj => ({
members: obj.members.map(
member => ({ ...member, no: no++ })
)
})
);
console.log(mapped);
You can use the map parameter thisArg.
map(function(element, index, array) { /* … */ }, thisArg)
const groupMembersByTitle = [{
members: [{ id: 'uuid' }, { id: 'uuid' }]
}, {
members: [{ id: 'uuid' }, { id: 'uuid' }]
}];
const r = groupMembersByTitle.map(function(o1) {
return ({
members: o1.members.map(
o2 => ({
...o2,
no: ++this.acc
})
)
});
}, { acc: 0 });
console.log(r);
function recursiveFunction(data, index) {
if(Array.isArray(data)) {
return data.reduce((acc, el) => this.recursiveFunction(el, acc), index);
} else if(data.members) {
return this.recursiveFunction(data.members, index);
} else {
data.no = index;
return index + 1;
}
}
const groupMembersByTitle = [
{
members: [
{
id: 'uuid'
},
{
id: 'uuid'
}
]
},
{
members: [
{
id: 'uuid'
},
{
id: 'uuid'
}
]
}];
const res = recursiveFunction(groupMembersByTitle, 0);
console.log(groupMembersByTitle);
console.log(res);
You can do it using Array.prototype.map twice and use the indices of the arrays to calculate the no.
const
data = [
{ members: [{ id: "uuid" }, { id: "uuid" }] },
{ members: [{ id: "uuid" }, { id: "uuid" }] },
],
result = data.map(({ members }, i) =>
members.map((m, j) => ({
...m,
no: i * (i ? data[i - 1].members.length : 1) + j + 1,
}))
);
console.log(result);

How to loop through two arrays of objects and get a new array with some data modified?

How to loop through two arrays of objects and get a new array with some data modified?
Arrays:
const products = [
{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Tees',
},
];
const categories = [
{
name: 'Jeans',
},
{
name: 'Tees',
},
];
Need new categories array like this with new prop productCount:
const newCategories = [
{
name: 'Jeans',
productCount: 2,
},
{
name: 'Tees',
productCount: 0,
},
];
I tried this way but it doesn't work:
const newArr = categories.map((category) => {
let count = 0;
const index = products.findIndex((product) => category.name === product.category);
if (index > -1) {
return {
...category,
productCount: count++,
};
}
return {
...category,
productCount: 0,
};
});
Increasing the count number will not in that case because it will always start with zero. Instead, you can use the filter() method to find the number of products with a specific category and assign this number to productCount attribute.
const products = [{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Tees',
},
];
const categories = [{
name: 'Jeans',
},
{
name: 'Tees',
},
];
const newArr = categories.map((category) => {
const numberOfItems = products.filter((product) => category.name === product.category);
return {
...category,
productCount: numberOfItems.length,
};
});
console.log(newArr)
You can create an object and the transform it to array, something like this:
const products = [
{
brand: "Levis",
category: "Jeans"
},
{
brand: "Levis",
category: "Jeans"
},
{
brand: "Levis",
category: "Tees"
}
];
const categoriesObj = {};
products.forEach(({ brand, category }) => {
categoriesObj[category] ??= {
name: category,
productCount: 0
};
++categoriesObj[category].productCount;
});
const newCategories = Object.values(categoriesObj);
console.log(newCategories);
You can use the Array#Map method and add a productCount property using the Array#filter method
const products = [{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Jeans',
},
{
brand: 'Levis',
category: 'Tees',
},
];
const categories = [{
name: 'Jeans',
},
{
name: 'Tees',
},
];
const newCategories = [...categories].map(category => ({
...category,
productCount: products.filter(product => product.category === category.name).length
}))
console.log(newCategories)
You could do this with Array.reduce(), incrementing the productCount for each item. This should also be efficient, requiring only one iteration of the products array.
We'd run the reduce over both arrays, ensuring that we'll end up with a productCount of zero where no products for that category exist.
const products = [ { brand: 'Levis', category: 'Jeans', }, { brand: 'Levis', category: 'Jeans', }, { brand: 'Levis', category: 'Tees', }, ];
const categories = [ { name: 'Jeans', }, { name: 'Tees', }, { name: 'Foo', } ];
const result = Object.values([...categories, ...products].reduce((acc, { brand, category, name }) => {
const key = name || category;
acc[key] = acc[key] || { name: key, productCount: 0 };
if (category) acc[key].productCount++;
return acc;
}, {}));
console.log('Result:', result);
.as-console-wrapper { max-height: 100% !important; }

How to change all occurrences of an object key in an array of objects

I have this sample data:
const data = [
{
id: 1,
title: 'Sports',
menus: [
{
id: 2,
title: 'Basketball',
menus: [
{
id: 3,
title: 'NBA',
},
{
id: 4,
title: 'NCAA',
},
{
id: 5,
title: 'G-League',
},
],
},
],
},
{
id: 100,
title: 'Names',
menus: [],
},
];
I want to change all the menus keys into children, so the result would be:
const result = [
{
id: 1,
title: 'Sports',
children: [
{
id: 2,
title: 'Basketball',
children: [
{
id: 3,
title: 'NBA',
},
{
id: 4,
title: 'NCAA',
},
{
id: 5,
title: 'G-League',
},
],
},
],
},
{
id: 100,
title: 'Names',
children: [],
},
];
I'm trying with this code:
const replacer = { menus: 'children' };
const transform = useCallback(
(obj) => {
if (obj && Object.getPrototypeOf(obj) === Object.prototype) {
return Object.fromEntries(Object.entries(obj).map(([k, v]) => [replacer[k] || k, transform(v)]));
}
return obj;
},
[replacer]
);
but it only changes the keys at the first level. How can I make it work?
You can use a recursive function that makes use of destructuring:
const replaceKey = arr =>
arr.map(({menus, ...o}) =>
menus ? {...o, children: replaceKey(menus)} : o);
const data = [{id: 1,title: 'Sports',menus: [{id: 2,title: 'Basketball',menus: [{id: 3,title: 'NBA',},{id: 4,title: 'NCAA',},{id: 5,title: 'G-League',},],},],},{id: 100,title: 'Names',menus: [],},];
console.log(replaceKey(data));
To provide the old/new key dynamically, use the following variant:
const replaceKey = (arr, source, target) =>
arr.map(({[source]: v, ...o}) =>
v ? {...o, [target]: replaceKey(v, source, target)} : o);
const data = [{id: 1,title: 'Sports',menus: [{id: 2,title: 'Basketball',menus: [{id: 3,title: 'NBA',},{id: 4,title: 'NCAA',},{id: 5,title: 'G-League',},],},],},{id: 100,title: 'Names',menus: [],},];
console.log(replaceKey(data, "menus", "children"));
This code assumes that values for the given key are arrays. If for some reason their values could be something else, then the code needs a bit more extension:
const data = [{id: 1,title: 'Sports',menus: [{id: 2,title: 'Basketball',menus: [{id: 3,title: 'NBA',},{id: 4,title: 'NCAA',},{id: 5,title: 'G-League',},],},],},{id: 100,title: 'Names',menus: 13,},];
const replaceKey = (arr, source, target) =>
Array.isArray(arr) ? arr.map(({[source]: value, ...o}) =>
value !== undefined ? {...o, [target]: replaceKey(value, source, target)} : o
) : arr;
console.log(replaceKey(data, "menus", "children"));
To see the effect of this code, the value for the very last menus key was changed to 13.
If the object is not big:
let data=[{id:1,title:'Sports',menus:[{id:2,title:'Basketball',menus:[{id:3,title:'NBA',},{id:4,title:'NCAA',},{id:5,title:'G-League',},],},],},{id:100,title:'Names',menus:[],},];
data = JSON.parse(JSON.stringify(data).replace(/"menus"\:/g,'"children":'))
console.log(data)
check this package: paix: that's take original source object and desired keys replacement then return a new object with desired keys, ex:
npm i paix
import { paix } from 'paix';
const data = [
{
id: 1,
title: 'Sports',
menus: [
{
id: 2,
title: 'Basketball',
menus: [
{
id: 3,
title: 'NBA',
},
],
},
],
},
{
id: 100,
title: 'Names',
menus: [],
},
];
const keys_swap = {menus: "children"};
const result = data.map(i => paix(i, keys_swap));

How to convert array of objects into enum like key value pair in javascript?

I have an array
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
I am trying it to reduce it to the below given output , However I am stuck
Output
{0:"read-web-courses",1:"example",2:"t_gql",3:"ddddd"}
You could map the wanted property and assign the pairs to the object.
const
array = [{ name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }],
result = Object.assign({}, array.map(({ name }) => name));
console.log(result);
You can use Array.reduce like below.
const a = [
{ name: "read-web-courses" },
{ name: "example" },
{ name: "t_gql" },
{ name: "ddddd" },
];
const convert = arr => (
arr.reduce((total, value, index) => {
total[index] = value.name;
return total;
}, {})
)
console.log(convert(a));
This is accomplished using Array#reduce, where you can use the index from the reduce callback as the key of the new object:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = a.reduce((r, o, i) => {
r[i] = o.name;
return r;
}, {});
console.log(res);
Also one more approach using Object#fromEntries and Array#map, where each object is converted to an array of key, value pairs:
const a = [ { name: "read-web-courses" }, { name: "example" }, { name: "t_gql" }, { name: "ddddd" }];
const res = Object.fromEntries(a.map((o, i) => [i, o.name]));
console.log(res)

How does JS filter the contents of an array without confusion

I want to filter the content of 'phone'
I have the following code:
var testList = [{
content:[
{id:1,uId:1,text:"apple", category: "phone"},
{id:2,uId:2,text:"nick",category: "life"},
{id:3,uId:3,text:"samsung",category: "phone"}],
user:[
{id:1,name: "Joe"},
{id:2,name: "red"},
{id:3,name: "blue"}
]
}]
const newArrys = testList
.filter((element) =>
element.content.some((subElement) => subElement.category == "phone"))
.map(element => {
return Object.assign({}, element, {
content: element.content.filter(subElement => subElement.category == "phone")
});
});
console.log(newArrys);
These are the returns:
[{
content:[
{id:1,uId:1,text:"apple", category: "phone"},
{id:3,uId:3,text:"samsung",category: "phone"}],
user:[
{id:1,name: "Joe"},
{id:2,name: "red"},
{id:3,name: "blue"}
]
}]
I want the result:
[{
content:[
{id:1,uId:1,text:"apple", category: "phone"},
{id:3,uId:3,text:"samsung",category: "phone"}],
user:[
{id:1,name: "Joe"},
{id:3,name: "blue"}
]
}]
How should I filter 'user'? , and correspond to 'content'
Can you help me? thank you
You can build a Set of id's that are having category as phone and then filter values based on the Set
var testList = [{content:[{id:1,uId:1,text:"apple", category: "phone"},{id:2,uId:2,text:"nick",category: "life"},{id:3,uId:3,text:"samsung",category: "phone"}],
user:[{id:1,name: "Joe"},{id:2,name: "red"},{id:3,name: "blue"}]}]
let final = testList.map(v => {
let mapper = new Set(v.content.filter(({
category
}) => category === "phone").map(({
id
}) => id))
return Object.fromEntries(Object.entries(v).map(([key, value]) => {
value = value.filter(({
id
}) => mapper.has(id))
return [key, value]
}).filter(([_, value]) => value))
})
console.log(final)
if Object.fromEntries is not supported
var testList = [{content:[{id:1,uId:1,text:"apple", category: "phone"},{id:2,uId:2,text:"nick",category: "life"},{id:3,uId:3,text:"samsung",category: "phone"}],
user:[{id:1,name: "Joe"},{id:2,name: "red"},{id:3,name: "blue"}]}]
let final = testList.map(v => {
let mapper = new Set(v.content.filter(({
category
}) => category === "phone").map(({
id
}) => id))
return Object.entries(v).map(([key, value]) => {
value = value.filter(({
id
}) => mapper.has(id))
return [key, value]
}).filter(([_, value]) => value).reduce((op,[k,v])=>{
op[k] = v
return op
},{})
})
console.log(final)
You could filter the indices first and then filter by wanted indices.
var testList = [{ content:[{ id: 1, uId: 1, text: "apple", category: "phone" }, { id: 2, uId: 2, text: "nick", category: "life" }, { id: 3, uId: 3, text: "samsung", category: "phone" }], user:[{ id: 1, name: "Joe" }, { id: 2, name: "red" }, { id: 3, name: "blue" }] }],
result = testList.map(o => {
var indices = [...o.content.keys()].filter(i => o.content[i].category === 'phone');
return Object.assign({}, ...['content', 'user'].map(k => ({ [k]: o[k].filter((_, i) => indices.includes(i)) })));
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Filter the content to find the category items and after filter the users in the list intens found.
var list = [
{
content:[
{id:1,uId:1,text:"apple", category: "phone"},
{id:2,uId:2,text:"nick",category: "life"},
{id:3,uId:3,text:"samsung",category: "phone"}
],
user:[
{id:1,name: "Joe"},
{id:2,name: "red"},
{id:3,name: "blue"}
]
}
];
const result = list.map(items => {
const content = items.content.filter(c => c.category === 'phone');
const users = items.user.filter(u => content.find(c => u.id === c.id));
return {
content: content,
user: users,
}
});
console.log(result);

Categories

Resources