Move Objects With Same Key Value Into An Array - JavaScript - javascript

I am trying to achieve an operation where Ι am not sure where to start with.
 Down below is my initial object:
[
{ type: "1", name: "Anthony" },
{
type: "1",
name: "Linus",
},
{
type: "2",
name: "Sebastin",
},
]
What I am trying to achieve is to move the objects which has same type inside an array and have a key value, named title and string type.
I am trying to produce an output equivalent to this and I am not sure where to begin with. Any help will be useful and appreciated. Thanks in advance <3
[
{
title: "1",
sub_items: [
{
type: "1",
name: "Anthony",
},
{
type: "1",
name: "Linus",
},
],
},
{
type: "2",
name: "Sebastin",
},
];

You can use Array.reduce() to group the input items by type/title and create the desired output:
const input = [{ "type":"1", "name":"Anthony" }, { "type": "1", "name": "Linus" }, { "type":"2", "name":"Sebastin" }]
const result = Object.values(input.reduce((acc, { type, name }) => {
acc[type] = acc[type] || { title: type, sub_items: [] };
acc[type].sub_items.push({ type, name });
return acc;
}, {}));
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

You can make it with Array.reduce
const data = [
{ type: "1", name: "Anthony" },
{
type: "1",
name: "Linus",
},
{
type: "2",
name: "Sebastin",
},
];
const output = data.reduce((acc, curr, index, list) => {
const matchNodes = list.filter((node) => node.type === curr.type);
if (matchNodes.length > 1) {
const accNode = acc.find((item) => item.title === curr.type);
if (accNode) {
accNode.sub_items.push(curr);
} else {
acc.push({
title: curr.type,
sub_items: [curr],
});
}
} else {
acc.push(curr);
}
return acc;
}, []);
console.log(output);

Related

Show ID of Duplicate Values in Array of Object

I found here this code and works good. But I also need to know the "id" which is multible in use. e.g. in another array
var data = [
{"id":"1","Group":"Wohnzimmer","Light":"Diele", "type":"ct"},
{"id":"1","Group":"Wohnzimmer","Light":"Diele", "type":"ct"},
{"id":"2","Group":"Wohnzimmer","Light":"Diele", "type":"bri"},
{"id":"3","Group":"Wohnzimmer","Light":"Diele", "type":"color"},
{"id":"3","Group":"Wohnzimmer","Light":"Diele", "type":"color"},
]
var a = data.reduce((accumulator, current) => {
if (checkIfAlreadyExist(current)) {
return accumulator;
} else {
return [...accumulator, current];
}
function checkIfAlreadyExist(currentVal) {
return accumulator.some((item) => {
return (item.id === currentVal.id &&
item.Light === currentVal.Light &&
item.type === currentVal.type);
});
}
}, []);
console.log(a);
Reduced (it works fine!):
[{
Group: "Wohnzimmer",
id: "1",
Light: "Diele",
type: "ct"
}, {
Group: "Wohnzimmer",
id: "2",
Light: "Diele",
type: "bri"
}, {
Group: "Wohnzimmer",
id: "3",
Light: "Diele",
type: "color"
}]
Now, I need also the result of the deleted objects, like the following:
[{
Group: "Wohnzimmer",
id: "1",
Light: "Diele",
type: "ct"
},{
Group: "Wohnzimmer",
id: "3",
Light: "Diele",
type: "color"
}]
You can do this efficiently in linear time:
let key = obj => [obj.id, obj.Light, obj.type].join('##')
let seen = new Set,
unique = [],
removed = []
for (let obj of data) {
let k = key(obj);
(seen.has(k) ? removed : unique).push(obj)
seen.add(k)
}
use array.prototype.map and array.prototype.some
var values = [
{ name: 'someName1' },
{ name: 'someName2' },
{ name: 'someName4' },
{ name: 'someName2' }
];
var valueArr = values.map(function(item){ return item.name });
var isDuplicate = valueArr.some(function(item, idx){
return valueArr.indexOf(item) != idx
});
console.log(isDuplicate);
Using you current logic you could archive your preferred output with small changes, use a object instead with two arrays instead.
var data = [
{ id: "1", Group: "Wohnzimmer", Light: "Diele", type: "ct" },
{ id: "1", Group: "Wohnzimmer", Light: "Diele", type: "ct" },
{ id: "2", Group: "Wohnzimmer", Light: "Diele", type: "bri" },
{ id: "3", Group: "Wohnzimmer", Light: "Diele", type: "color" },
{ id: "3", Group: "Wohnzimmer", Light: "Diele", type: "color" },
];
var { unique, removed } = data.reduce(
(accumulator, current) => {
if (checkIfAlreadyExist(current)) {
return {
...accumulator,
removed: [...accumulator.removed, current],
};
} else {
return {
...accumulator,
unique: [...accumulator.unique, current],
};
}
function checkIfAlreadyExist(currentVal) {
return accumulator.unique.some((item) => {
return (
item.id === currentVal.id &&
item.Light === currentVal.Light &&
item.type === currentVal.type
);
});
}
},
{
unique: [],
removed: [],
}
);
console.log("Unique");
console.log(unique);
console.log("Removed");
console.log(removed);
Just create another array to store deleted items and if checkIfAlreadyExist returns true push current into the array.
var data = [
{"id":"1","Group":"Wohnzimmer","Light":"Diele", "type":"ct"},
{"id":"1","Group":"Wohnzimmer","Light":"Diele", "type":"ct"},
{"id":"2","Group":"Wohnzimmer","Light":"Diele", "type":"bri"},
{"id":"3","Group":"Wohnzimmer","Light":"Diele", "type":"color"},
{"id":"3","Group":"Wohnzimmer","Light":"Diele", "type":"color"},
]
var deleted = []
var a = data.reduce((accumulator, current) => {
if (checkIfAlreadyExist(current)) {
deleted.push(current)
return accumulator;
} else {
return [...accumulator, current];
}
function checkIfAlreadyExist(currentVal) {
return accumulator.some((item) => {
return (item.id === currentVal.id &&
item.Light === currentVal.Light &&
item.type === currentVal.type);
});
}
}, []);
console.log(a);
console.log(deleted)

Compare two array of objects and filter element not present in second array

Suppose I have two array of object as:
const array1 = [
{ name: 'detail1', title: 'detail1' },
{ name: 'detail2 ', title: 'detail2 ' },
{ name: 'detail3', title: 'detail3' },
{ name: 'detail4', title: 'detail4' },
{ name: 'detail5', title: 'detail5' },
{ name: 'detail6', title: 'detail6' },
{ name: 'detail7', title: 'detail7' }
]
const array2 = [
{ name: 'detail1', title: 'detail1' },
{ name: 'detail2 ', title: 'detail2 ' },
{ name: 'detail3', title: 'detail3' },
{ name: 'detail4', title: 'detail4' },
]
I want to compare two arrays i.e. array1 and array2 and get the missing element of aaray2.
For this I tried as:
var absent = array2.filter(e=>!array1.includes(e));
But I am unable to get missing element of array2.
My expected O/P :
[ { name: 'detail5', title: 'detail5' },
{ name: 'detail6', title: 'detail6' },
{ name: 'detail7', title: 'detail7' }]
These are all the elements which are not present in array2.
What exactly am I doing wrong here?
Please let me know if anyone needs any further information.
You could build a normalised object with key and values and filter the objects.
const
array1 = [{ name: 'detail1', title: 'detail1' }, { name: 'detail2 ', title: 'detail2 ' }, { name: 'detail3', title: 'detail3' }, { name: 'detail4', title: 'detail4' }, { name: 'detail5', title: 'detail6' }, { name: 'detail7', title: 'detail7' }, { name: 'detail8', title: 'detail8' }],
array2 = [{ name: 'detail1', title: 'detail1' }, { name: 'detail2 ', title: 'detail2 ' }, { name: 'detail3', title: 'detail3' }, { name: 'detail4', title: 'detail4' }],
sortEntriesByKey = ([a], [b]) => a.localeCompare(b),
filter = array2.reduce((r, o) => {
Object
.entries(o)
.sort(sortEntriesByKey)
.reduce((o, [k, v]) => (o[k] ??= {})[v] ??= {}, r);
return r;
}, {});
absent = array1.filter((o) => {
let f = filter;
return !Object
.entries(o)
.sort(sortEntriesByKey)
.every(([k, v]) => f = f[k]?.[v]);
});
console.log(absent);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Edit: you want objects in A not in B.
It is ideal to loop through A, find if the element exists in B. If yes, then do not include it.
In javacript object references are compared when you do "==" or "===" or other array search methods.
{} == {} will return false. You can check in your dev console.
In your case, you will have to check specific properties.
var absent = array1.filter(e=>{
let findInd = array2.findIndex((a)=>{
return (a.name == e.name && a.title == e.title);});
return (findInd == -1); });
In the inner findIndex, I am finding index based on a condition. In filter method, I am returning true only if that index is -1(not found).
This worked for me:
let cart = [{
"id": "6304a51af5726921c0dadd64",
"qty": 1
},
{
"id": "8704a51af5726921c0dadd64",
"qty": 1
},
{
"id": "4704a51af5726921c0dadd64",
"qty": 1
}
]
let cartList = [{
"id": "6304a51af5726921c0dadd64",
"qty": 1
},
{
"id": "9704a51af5726921c0dadd64",
"qty": 1
}
]
let test = cart.some((element) =>
cartList.some((e) => element.id === e.id)
);
console.log(" if any single object matched:", test);
let test1 = cart.filter((element) =>
cartList.some((e) => element.id === e.id)
);
console.log("display matching objects :", test1);

Check if an element is common between 2 arrays and then assign values from it

In my angular 8 application, I have 2 arrays:
array1 = [{
"SubType": "2|3|4|5|6",
},
{
"SubType": "2",
},
{
"SubType": "3|4",
},
{
"SubType": "6",
},
{
"SubType": "3|6",
},
]
&
array2 = [{
"id": 2,
"type": "1",
},
{
"id": 3,
"type": "5",
},
{
"id": 4,
"type": "4",
},
{
"id": 5,
"type": "3",
},
{
"id": 6,
"type": "2",
}
]
I am trying to check each "SubType" in array1 and see if that element(id) is present in array2 and if present assign its "type" to a variable. "SubType" is | separated which I and converting to an array using array1..split('|'). This when assigning to a variable will need to be comma separated. I tried using array filter but I am not able to find a way to loop thorough the second array. Can anyone help?
array1.forEach(reg => {
if (reg.SubType) {
let subTypeTemp = reg.SubType.split('|');
let tempVariable = subTypeTemp.some(ele => {
let stringToassign = '';
for (let i = 0; i < array2.length; i++) {
if (ele == array2[i].id) {
stringToassign += array2[i].type + ",";
}
}
})
}
})
const array1 = [
{
SubType: "2|3|4|5|6"
},
{ SubType: "2" },
{ SubType: "3|4" },
{ SubType: "6" },
{ SubType: "3|6" }
];
const array2 = [
{
id: 2,
type: "1"
},
{ id: 3, type: "5" },
{ id: 4, type: "4" },
{ id: 5, type: "3" },
{ id: 6, type: "2" }
];
const array2Obj = array2.reduce(
(acc, curr) => ({
...acc,
[curr.id]: curr.type
}),
{}
);
const types = [];
array1.forEach(item => {
const sub_types = item.SubType.split("|");
sub_types.forEach(st => {
if (st in array2Obj) {
types.push(array2Obj[st]);
}
});
});
const types_str = [...new Set(types)].join(',');
console.log("types", types_str);
You could take a Map and prevent looping array2 over and over for getting type of a wanted id.
var array1 = [{ SubType: "2|3|4|5|6" }, { SubType: "2" }, { SubType: "3|4" }, { SubType: "6" }, { SubType: "3|6" }],
array2 = [{ id: 2, type: "1" }, { id: 3, type: "5" }, { id: 4, type: "4" }, { id: 5, type: "3" }, { id: 6, type: "2" }],
types = new Map(array2.map(({ id, type }) => [id.toString(), type])),
result = array1.map(({ SubType }) => SubType
.split('|')
.map(Map.prototype.get, types)
.join()
);
console.log(result);

Merge two array of objects together es6

Currently I have two different array of objects and my end result is I am trying to have one single array of objects.
const postIds = [
{ id: 4938960132 },
{ id: 5586491011 },
{ id: 4671908225 },
{ id: 4594788047 },
{ id: 4657970305 }
]
const images = [
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/rustic20coffee20table.jpeg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Amazing-Table-For-Flamboyant-Furniture-Home-Design-Ideas-With-Rustic-Furniture-Coffee-Table.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/envoy-lookout-rooftop-11b-780x520.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Alexanderplatz_03.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/mountain-landscape-wallpaper-29048-29765-hd-wallpapers.jpg%3Ft=1528912781831-6.jpeg' }
]
What I am hoping to have at the end is a data structure like the following
const newData = [
{ id: 4938960132, featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/rustic20coffee20table.jpeg%3Ft=1528912781831-6.jpeg' },
{ id: 5586491011, featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Amazing-Table-For-Flamboyant-Furniture-Home-Design-Ideas-With-Rustic-Furniture-Coffee-Table.jpg%3Ft=1528912781831-6.jpeg' },
{ id: 4671908225, featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/envoy-lookout-rooftop-11b-780x520.jpg%3Ft=1528912781831-6.jpeg' },
{ id: 4594788047, featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/mountain-landscape-wallpaper-29048-29765-hd-wallpapers.jpg%3Ft=1528912781831-6.jpeg'},
{ id: 4657970305, featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/mountain-landscape-wallpaper-29048-29765-hd-wallpapers.jpg%3Ft=1528912781831-6.jpeg' }
]
I've been trying a lot of different things here such as reduce, spread operator and other es6 functions but cannot seem to get the data structure that I am looking for.
Any help would be much appreciated
Assuming the two arrays have the same length:
const newData = [...postIds.map((postId, i) => Object.assign({}, postId, images[i]))];
Alternativelly, with ... operator:
const newData = [...postIds.map((item, i) => {
return {
...item,
...images[i]
};
})];
Working snippet:
const postIds = [
{ id: 4938960132 },
{ id: 5586491011 },
{ id: 4671908225 },
{ id: 4594788047 },
{ id: 4657970305 }
]
const images = [
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/rustic20coffee20table.jpeg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Amazing-Table-For-Flamboyant-Furniture-Home-Design-Ideas-With-Rustic-Furniture-Coffee-Table.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/envoy-lookout-rooftop-11b-780x520.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Alexanderplatz_03.jpg%3Ft=1528912781831-6.jpeg' },
{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/mountain-landscape-wallpaper-29048-29765-hd-wallpapers.jpg%3Ft=1528912781831-6.jpeg' }
]
const newData = [...postIds.map((item, i) => Object.assign({}, item, images[i]))];
console.log(newData)
You creduce both array by mapping the objects at the same index and by assigning to a new object.
This works for an arbitrary count of arrays.
const
postIds = [{ id: 4938960132 }, { id: 5586491011 }, { id: 4671908225 }, { id: 4594788047 }, { id: 4657970305 }],
images = [{ featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/rustic20coffee20table.jpeg%3Ft=1528912781831-6.jpeg' }, { featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Amazing-Table-For-Flamboyant-Furniture-Home-Design-Ideas-With-Rustic-Furniture-Coffee-Table.jpg%3Ft=1528912781831-6.jpeg' }, { featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/envoy-lookout-rooftop-11b-780x520.jpg%3Ft=1528912781831-6.jpeg' }, { featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/Alexanderplatz_03.jpg%3Ft=1528912781831-6.jpeg' }, { featuredImage: 'https://www.rusticfurnitureboston.com/hubfs/Blog_Media/mountain-landscape-wallpaper-29048-29765-hd-wallpapers.jpg%3Ft=1528912781831-6.jpeg' }],
result = [images, postIds].reduce(
(r, a) => a.map((o, i) => Object.assign({}, o, r[i])),
[]
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

How can I convert a JSON to another

I'm receiving a JSON from a Laravel API in this way:
[
{
"id":48,
"parentid":0,
"title":"Item 1",
"child_content":[
{
"id":49,
"parentid":48,
"title":"Itema 1.1",
},
{
"id":52,
"parentid":48,
"title":"Item 1.2",
}
]
},
{
"id":58,
"parentid":0,
"title":"Item 2",
"child_content":[
{
"id":59,
"parentid":58,
"title":"Itema 2.1",
},
{
"id":60,
"parentid":58,
"title":"Item 2.2",
}
]
}
]
and what I need is change the JSON into this:
{
"data":
[
{
"data":
{
"id":68,
"parentid":0,
"title":"Item 1"
},
"children":
[
{
"data":
{
"id":69,
"parentid":68,
"title":"Item 1.1"
},
},
{
"data":
{
"id":69,
"parentid":68,
"title":"Item 1.2"
}
}
]
}
]
}
I've been dealing with this... but I'm not able to find the way to do this properly...
How can I do this in PHP or Javascript / TypeScript (Angular 2).
Thank you in advance.
This should achieve your goal. Basically I'm just grabbing child_content, renaming it to children and copying the 3 other attributes. The children.map iteration is putting the existing data inside an object with a key of data:
const input = [{"id":48,"parentid":0,"title":"Item 1","child_content":[{"id":49,"parentid":48,"title":"Itema 1.1"},{"id":52,"parentid":48,"title":"Item 1.2"}]},{"id":58,"parentid":0,"title":"Item 2","child_content":[{"id":59,"parentid":58,"title":"Itema 2.1"},{"id":60,"parentid":58,"title":"Item 2.2"}]}]
const output = {
data: input.map((data) => {
const {
child_content: children,
id,
parentId,
title,
} = data;
return {
id,
parentId,
title,
children: children.map(data => ({data})),
};
})
}
console.log(output);
You can use JavaScript Array.prototype.map():
var json = [{"id": 48,"parentid": 0,"title": "Item 1","child_content": [{"id": 49,"parentid": 48,"title": "Itema 1.1",}, {"id": 52,"parentid": 48,"title": "Item 1.2",}]}, {"id": 58,"parentid": 0,"title": "Item 2","child_content": [{"id": 59,"parentid": 58,"title": "Itema 2.1",}, {"id": 60,"parentid": 58,"title": "Item 2.2",}]}],
result = {
data: json.map(function (item) {
return {
data: {
id: item.id,
parentid: item.parentid,
title: item.title
},
children: item.child_content.map(function (childItem) {
return {
data: {
id: childItem.id,
parentid: childItem.parentid,
title: childItem.title
}
}
})
};
})
};
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Assuming that the differences in the two datasets are due to copy/paste from different datasets, you can use the array map method to transform the data for you.
map works by iterating through each item of an array, and allows you to return a new item in the shape which you'd like.
var input = [{"id":48,"parentid":0,"title":"Item 1","child_content":[{"id":49,"parentid":48,"title":"Itema 1.1"},{"id":52,"parentid":48,"title":"Item 1.2"}]},{"id":58,"parentid":0,"title":"Item 2","child_content":[{"id":59,"parentid":58,"title":"Itema 2.1"},{"id":60,"parentid":58,"title":"Item 2.2"}]}];
var output = {
data: input.map(function(parent) {
// return a new object which contains the properties which you need
return {
data: {
id: parent.id,
parentid: parent.parentid,
title: parent.title
},
// children is an array, so we can use map again to transform them
children: parent.child_content.map(function(child) {
return {
data: {
id: child.id,
parentid: parent.id,
title: child.title
}
};
})
}
})
}
console.log(output);
You could convert the structure without mutating the original object with iterating and recursive calls of the convert function.
It works for any depth.
function convert(o) {
var temp = { data: {} };
Object.keys(o).forEach(function (k) {
if (k === 'child_content') {
temp.children = o[k].map(convert);
} else {
temp.data[k] = o[k];
}
});
return temp;
}
var data = [{ id: 48, parentid: 0, title: "Item 1", child_content: [{ id: 49, parentid: 48, title: "Itema 1.1" }, { id: 52, parentid: 48, title: "Item 1.2" }] }, { id: 58, parentid: 0, title: "Item 2", child_content: [{ id: 59, parentid: 58, title: "Itema 2.1" }, { id: 60, parentid: 58, title: "Item 2.2" }] }],
result = { data: data.map(convert) };
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Ok, what I finally did is maybe not too much elegant... but it works, probably I should create a recursive function to manage different nested levels. I took the #RobM solution and replicated the children functionality at the second level like this:
convert(input)
{
const output =
{
data: input.map((data) =>
{
const { children: children } = data;
delete data.children;
return {
data,
children: children.map(data =>
{
const { children: children } = data;
delete data.children;
return {
data,
children: children.map(data => ({data})),
};
}),
};
})
}
return output.data;
}

Categories