http://jsfiddle.net/0444046b/12/
I have a complex Array of objects, each object has it's own tag Array.
I also have just an object which should match one of the objects in the tag Array, and if so remove that tag.
Got some help here, however my example there was too simple, so far no luck with this below.
Basically I have the object tag and I need to remove it from the tags Array inside of tagsArray.
var tagsArray = [{
name: "group1",
tags: [
{
name: "1",
tag_id: "1234"
},
{
name: "2",
tag_id: "5678"
},
{
name: "3",
tag_id: "9012"
}
]
},
{
name: "group2",
tags: []
}
];
console.log(tagsArray[0]);
// Need to find this inside of tags inside of tagsArray and remove it:
var tag = {
name: "3",
tag_id: "9012"
}
var temp_array = [];
temp_array.push(tag);
var map = {};
tagsArray.forEach(function(obj, index) {
map[obj.tag_id] = index;
});
console.log(map);
temp_array.forEach(function(obj) {
if ( obj.tag_id ) {
tagsArray.splice(tagsArray[map[obj.tag_id]]);
console.log(tagsArray);
}
});
You can loop through each item in tagsArray and then filter our matching elements in the inner tags property.
var tagsArray = [{
name: "group1",
tags: [{
name: "1",
tag_id: "1234"
}, {
name: "2",
tag_id: "5678"
}, {
name: "3",
tag_id: "9012"
}]
}, {
name: "group2",
tags: []
}];
// Need to find this inside of tags inside of tagsArray and remove it:
var removeTag = {
name: "3",
tag_id: "9012"
}
var message = 'Before:<br>' + JSON.stringify(tagsArray) + '<br><br>';
tagsArray.forEach(function(element) {
element.tags = element.tags.filter(function(tag) {
return tag.name != removeTag.name && tag.tag_id != removeTag.tag_id;
})
});
message += 'After:<br>' + JSON.stringify(tagsArray);
document.body.innerHTML = message
The solution of Daniel Imms is totally fine, but this one also can solve your problem, and it is a bit faster.
var tagsArray = [{
name: "group1",
tags: [{
name: "1",
tag_id: "1234"
}, {
name: "2",
tag_id: "5678"
}, {
name: "3",
tag_id: "9012"
}]
}, {
name: "group2",
tags: [{
name: "4",
tag_id: "1012"
}]
}];
var removedTag = {
name: "4",
tag_id: "1012"
};
var message = 'Before:</br>' + JSON.stringify(tagsArray) + '</br></br>';
tagsArray.forEach(function(obj, i) {
obj.tags.forEach(function(tag, j) {
if (tag.tag_id === removedTag.tag_id && tag.name === removedTag.name) {
obj.tags.splice(j, 1);
return;
}
});
});
message += 'After:</br>' + JSON.stringify(tagsArray);
document.body.innerHTML = message
I tested with jsPerf and here is the link and here is the result.
Related
I have two array of objects.
const firstObj = [
{ Id: "1", Name: "Peter" },
{ Id: "2", Name: "John" },
{ Id: "12", Name: "jessy" },
];
const secondObj = [
{ Id: "1", Name: "Roa", original: { Id: "1" } },
{ Id: "2", Name: "John2", original: { Id: "2" } },
{ Id: "5", Name: "Rachel", original: { Id: "3" } },
];
Here, I am trying to filter data on the basis of Id and return the filtered firstObj
So, here firstObj has an entry { Id: "12", Name: "jessy" } this object whose Id does not match with the secondObj.original.Id so, firstObj will have the given result.
what I tried was
firstObj.filter(
firstObj,
secondObj.map((second) => {
return firstObj.Id === second.original.Id;
}),
);
But this does not work. Can any one help me out here , using Lodash or Js filter.
output would be -> [{"Id": "3", "Name": "jessy"}]
Is this what you are looking for?
const firstObj = [
{ Id: "1", Name: "Peter" },
{ Id: "2", Name: "John" },
{ Id: "12", Name: "jessy" },
];
const secondObj = [
{ Id: "1", Name: "Roa", original: { Id: "1" } },
{ Id: "2", Name: "John2", original: { Id: "2" } },
{ Id: "1", Name: "Rachel", original: { Id: "3" } },
];
const result = lodash.filter(firstObj, (firstItem) => {
return !lodash.some(secondObj, (secondItem) => {
return firstItem.Id === secondItem.original.Id;
});
});
Live: https://stackblitz.com/edit/js-addy5t?file=index.js
why use loadash for this. you can use native filter and find functions to achieve this
const filter = firstObj.filter(item => {
return secondObj.find(itm => itm.original.id === item.id)
});
You could use native method of Array.filter() and Array.some() to achieve the desired output.
Please check below working code snippet
ES6
const firstObj = [
{ Id: "1", Name: "Peter" },
{ Id: "2", Name: "John" },
{ Id: "12", Name: "jessy" },
],
secondObj = [
{ Id: "1", Name: "Roa", original: { Id: "1" } },
{ Id: "2", Name: "John2", original: { Id: "2" } },
{ Id: "1", Name: "Rachel", original: { Id: "3" } },
];
let result = firstObj.filter(({Id})=> !secondObj.some(item => item.original.Id === Id));
console.log(result)
This is my array
const arr = [
{ id: "1", hello: "hello1" },
{ id: "2", hello: "hello2" },
];
I want this code
const finalarr = [
{ id: "1", hello: "hello1", bye: 'bye1' },
{ id: "2", hello: "hello2", bye: 'bye2' },
];
Try with map:
var arr = [{ id: "1", hello: "hello1" },{ id: "2", hello: "hello2" }];
result = arr.map(elem=>({...elem, 'bye':`bye${elem.id}`})); // with attaching the id
result2 = arr.map((elem,i)=>({...elem, 'bye':`bye${i+1}`})); // by generating id;
console.log(result);
console.log(result2);
By using the below loop in your code you can get ur required output.
for (var i =0;i<arr.length;i++){
arr[i]["bye"] = "bye"+(i+1);
}
I have an Json Raw Data with Parent child relationship.I would like to generate Hierarchical json from flat with parent ID.I have tried below code its working fine but I would like to know how to remove children[] object if there is no data in children object.
var arry = [
{ Id: "1", Name: "abc", Parent: "", attr: "abc" },
{ Id: "2", Name: "abc", Parent: "1", attr: "abc" },
{ Id: "3", Name: "abc", Parent: "2", attr: "abc" },
{ Id: "4", Name: "abc", Parent: "2", attr: "abc" },
];
function convert(array) {
var map = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
obj.children = [];
map[obj.Id] = obj;
var parent = obj.Parent || "-";
if (!map[parent]) {
map[parent] = {
children: [],
};
}
map[parent].children.push(obj);
}
return map["-"].children;
}
var r = convert(arry);
console.log("array", r);
console.log("result", JSON.stringify(r));
I have the feeling that there might be a better way, but how about just traverse through the map properties and delete the ones with an empty children array?
var arry = [
{ Id: "1", Name: "abc", Parent: "", attr: "abc" },
{ Id: "2", Name: "abc", Parent: "1", attr: "abc" },
{ Id: "3", Name: "abc", Parent: "2", attr: "abc" },
{ Id: "4", Name: "abc", Parent: "2", attr: "abc" },
];
function convert(array) {
var map = {};
for (var i = 0; i < array.length; i++) {
var obj = array[i];
obj.children = [];
map[obj.Id] = obj;
var parent = obj.Parent || "-";
if (!map[parent]) {
map[parent] = {
children: [],
};
}
map[parent].children.push(obj);
}
for (let prop in map) {
if (map[prop].children.length === 0) {
delete map[prop].children;
}
}
return map["-"].children;
}
var r = convert(arry);
console.log("array", r);
console.log("result", JSON.stringify(r));
Using map-reduce can be done very easily in O(n)
const source = [
{ Id: "1", Name: "abc", Parent: "", attr: "abc" },
{ Id: "2", Name: "abc", Parent: "1", attr: "abc" },
{ Id: "3", Name: "abc", Parent: "2", attr: "abc" },
{ Id: "4", Name: "abc", Parent: "2", attr: "abc" },
];
function tree(data, id, pId) {
const [result] = data.reduce(
([r, map], item) => {
const d = { ...item, children: [] };
const loc = map[item[pId]];
if (loc) {
loc.children.push(d);
} else {
r.push(d);
}
map[item[id]] = d;
return [r, map];
},
[[], {}]
);
return result;
}
//console.log(JSON.stringify(tree(source, "Id", "Parent"), null, 4));
document.querySelector("pre").innerHTML = JSON.stringify(tree(source, "Id", "Parent"), null, 4)
.as-console {
min-height: 100% !important;
}
.as-console-row {
color: blue !important;
}
.code {
<pre class="code"></pre>
The need is to take objects like this:
[ { "first":
{ "children" : [{ "name": "abc", "detail":"123"},
{ "name": "def", "detail":"456"}
]
}},
{ "second":
{ "children" : [{ "name": "ghi", "detail":"123"},
{ "name": "jkl", "detail":"456"}
]
}},
{ "third":
{ "children" : [{ "name": "mno", "detail":"123"},
{ "name": "pqr", "detail":"456"}
]
}},
{ "fourth":
{ "children" : [{ "name": "stu", "detail":"123"},
{ "name": "vwx", "detail":"456"}
]
}},
{ "fifth":
{ "children" : [{ "name": "yz", "detail":"123"},
{ "name": "abc", "detail":"456"}
]
}},
{ "sixth":
{ "children" : [{ "name": "def", "detail":"123"},
{ "name": "ghi", "detail":"456"}
]
}}
]
and then create a flattened array of unique values (options for a select) from the name field of the children that looks like this:
[{"value":"abc", "label":"abc"},
{"value":"def", "label":"def"},
{"value":"ghi", "label":"ghi"},
{"value":"jkl", "label":"jkl"},
{"value":"mno", "label":"mno"},
{"value":"pqr", "label":"pqr"},
{"value":"stu", "label":"stu"},
{"value":"vwx", "label":"vwx"},
{"value":"yz", "label":"yz"}
]
The code below is working, but it looks like it is inefficient because it appears to make many passes over the array:
[
...new Set(
[].concat.apply([], bases.map((base) => {
if (!base.children || base.children.length === 0) return;
return base.children}
)).map((child) => child.name)
)
].map((optName) => {return {value: optName, label: optName};})
If it is possible, how can this same result be achieved without as many iterations across the array.
Firstly, as a rule of thumb, you shouldn't worry too much about performance until you have a reason to do so.
Secondly, chaining the array prototype functions (e.g. map, forEach, filter) will require multiple iterations by design.
Thirdly, there's no reason to assume multiple iterations is slower than a single iteration if the work done within the iterations is the same anyways. I.e. incrementing an index and comparing it with an array length isn't going to be the bottleneck compared to pushing objects into arrays and check set entries.
Here's a (IMO) cleaner snippet to extract unique names from your array:
let bases = [{
children: [{
name: "abc",
detail: "123"
},
{
name: "def",
detail: "456"
}
]
}, {
children: [{
name: "abc" ,
detail: "123"
},
{
name: "xyz" ,
detail: "456"
}
]
},
{}
];
let output = bases
.flatMap(b => b.children || [])
.map(c => c.name)
.filter((v, i, a) => a.indexOf(v) === i) // filter unique values
.map(name => ({
value: name,
label: name,
}));
console.log(output);
Now if you really want to do all this in a single iteration, that too is possible, but harder to read:
let bases = [{
children: [{
name: "abc",
detail: "123"
},
{
name: "def",
detail: "456"
}
]
}, {
children: [{
name: "abc" ,
detail: "123"
},
{
name: "xyz" ,
detail: "456"
}
]
},
{}
];
let output = [];
let seenNames = {};
for (base of bases) {
if (!base.children)
continue;
for (child of base.children) {
let name = child.name;
if (seenNames[name])
continue;
seenNames[name] = true;
output.push({
value: name,
label: name,
});
}
}
console.log(output);
You could take Array#flatMap for getting a flat representation of data for using unique values and map new objects.
var data = [{ first: { children: [{ name: "abc", detail: "123" }, { name: "def", detail: "456" }] } }, { second: { children: [{ name: "ghi", detail: "123" }, { name: "jkl", detail: "456" }] } }, { third: { children: [{ name: "mno", detail: "123" }, { name: "pqr", detail: "456" }] } }, { fourth: { children: [{ name: "stu", detail: "123" }, { name: "vwx", detail: "456" }] } }, { fifth: { children: [{ name: "yz", detail: "123" }, { name: "abc", detail: "456" }] } }, { sixth: { children: [{ name: "def", detail: "123" }, { name: "ghi", detail: "456" }] } }],
result = Array.from(
new Set(data
.flatMap(Object.values)
.flatMap(({ children }) => children.map(({ name }) => name))
),
value => ({ value, label: value })
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
I am getting one json in this structure:
{
data: {
ads: [
{
name: "0",
id: "81"
},
{
name: "0",
id: "82"
}
]
}
}
i want to create one more json from the existing one like this.
{
json{
81:[
{
name: "a",
id: "81"
},
]
82:[
{
name: "c",
id: "82"
}
]
}
}
I am not getting how to create according to the id. Can anyone help me in this. using javascript i am want to create this
You can use bracket notation to achieve this:
var obj = {
data: {
ads: [
{
name: "0",
id: "81"
},
{
name: "0",
id: "82"
}
]
}
};
var newobj = {
json: {}
};
for(var i in obj.data.ads) {
var a = obj.data.ads[i];
if(!(a.id in newobj.json)) {
newobj.json[a.id] = [];
}
newobj.json[a.id].push({ name: a.name, id: a.id });
}
Here is a fiddle to demonstrate.