How to use filter or forEach in javascript to output only the objects whithout parentId and the objects with only the first level of parentId.
Should output objects with ids: 1681, 1682, and 1683.
Should not output objects with ids: 1685, 1686 and 1687.
array = [ {
"id": 1681,
"label": "1",
"url": "page1",
},
{
"id": 1682,
"label": "2",
"url": "page1",
},
{
"id": 1683,
"label": "a",
"url": "page1",
"parentId": 1681,
},
{
"id": 1685,
"label": "aa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1686,
"label": "aaa",
"url": "page1",
"parentId": 1683,
},
{
"id": 1687,
"label": "aaaa",
"url": "page1",
"parentId": 1683,
}
]
Something like this...
array.filter(({item}) => !item.parentId ? item.id : item.parentId)
We have to save the information if we already found a parentId from inside the filter function. A handy way to do this is by using the prefix operator ++ on a counter. This way we get around an explicit, long assignment with =. Instead we make it before.
Additionally with destructuring assignment we can extract the parentId comfortably of the array items and write a really short filter:
array=[{id:1681,label:"1",url:"page1"},{id:1682,label:"2",url:"page1"},{id:1683,label:"a",url:"page1",parentId:1681},{id:1685,label:"aa",url:"page1",parentId:1683},{id:1686,label:"aaa",url:"page1",parentId:1683},{id:1687,label:"aaaa",url:"page1",parentId:1683}];
window.parentIdCount = 0;
window.filtered =
array.filter(({parentId}) => !parentId || ++parentIdCount <= 1)
console.log(filtered)
Something like this ought to work:
const result = array.filter(object => object.parentId === undefined);
Related
Let's say we have some houses represented as JSON. Something like this:
[
{
"id": "1",
"code": "1",
"name": "Smith's",
"children": [
{
"id": "",
"code": "11",
"name": "Kitchen",
"children": [
{
"id": "",
"code": "111",
"name": "Sink",
"children": []
}
]
},
{
"id": "",
"code": "12",
"name": "Living Room",
"children": [
{
"id": "",
"code": "121",
"name": "Television",
"children": [
{
"id": "",
"code": "1211",
"name": "Panel buttons",
"children": [
{
"id": "",
"code": "12111",
"name": "Power button",
"children": []
},
{
"id": "",
"code": "12112",
"name": "Colors adjust button",
"children": []
}
]
},
{
"id": "",
"code": "1221",
"name": "Screen",
"children": []
}
]
}
]
}
]
},
{
"id": "2",
"code": "2",
"name": "Taylor's",
"children": [
// Here goes all house places and items like the example above
]
},
{
"id": "1",
"code": "1",
"name": "Wilson's",
"children": [
// Here goes all house places and items like the example above
]
}
]
Take notice that the "code" property, found in each item, is something to represent the "path" until that item, carrying its parents "code" property concatenated with its own position by incremental order. So the code "11" means house 1 and child 1. And 212 would be house 2, child 1, child 2. Also take notice that all items follow the same type. In other words, every item has a children that follows its own type. So, it could be infinite.
Now, I'd like to maintain these structure. Adding items, updating items and so on. Let's say we want to add a carpet in Smith's living room. We would go deep in the structure 2 levels, which are Smith's house (index 0 of the array) and living room (index 1 of the children array). And then add a carpet.
The problem is it won't be 2 levels in all cases. What if I wanted to add a bathroom? It would be level 1, alongside with kitchen in living room (the first children). What if I'd like to add a microwave in the kitchen and add to it buttons, display, etc?
I think I'm a recursive scenario where I have to visit all items and, if it is the one I'm looking to reach at, add/updated it.
I've tried following this example
I couldn't figure it out how to bring it to my case. though.
I appreciate if your contribution is in JavaScript, but feel free to represent it in other language in case you are better in other language =).
There are indeed some questions, like for instance what happens if you have more than 10 items as child and why do you need it?
And what happens if you remove any item on any level? will you recursively start updating all codes?
Nevertheless I gave it a go. In essence what I do in the code is first search for the parent (example: Kitchen) where you want to add it to and then add the new child item (example: Carpet) to it.
The search is a typical recursive search.
The child addition is a typical addition to an array.
For argument's sake I assumed that the fields code always exist and that children is always an array.
// Actual code is underneath the declaration of this array
let houseList = [
{
"id": "1",
"code": "1",
"name": "Smith's",
"children": [
{
"id": "",
"code": "11",
"name": "Kitchen",
"children": [
{
"id": "",
"code": "111",
"name": "Sink",
"children": []
}
]
},
{
"id": "",
"code": "12",
"name": "Living Room",
"children": [
{
"id": "",
"code": "121",
"name": "Television",
"children": [
{
"id": "",
"code": "1211",
"name": "Panel buttons",
"children": [
{
"id": "",
"code": "12111",
"name": "Power button",
"children": []
},
{
"id": "",
"code": "12112",
"name": "Colors adjust button",
"children": []
}
]
},
{
"id": "",
"code": "1221",
"name": "Screen",
"children": []
}
]
}
]
}
]
},
{
"id": "2",
"code": "2",
"name": "Taylor's",
"children": [
// Here goes all house places and items like the example above
]
},
{
"id": "1",
"code": "1",
"name": "Wilson's",
"children": [
// Here goes all house places and items like the example above
]
}
]
addChild(houseList,"11",{name:"Carpet" });
addChild(houseList,"1211",{name: "Volume Up Button"});
addChild(houseList,"1211",{name: "Volume Down Button"});
console.log('new houselist', houseList);
// child is just what you want to add and the parentCode refers to where you want to add it to
function addChild(houseList, parentCode, child) {
let parent = findInHouseList(houseList,parentCode,child);
let amountOfChildren = parent.children.length;
let newCodeName = parentCode +""+ (amountOfChildren+1);
child = {...{id: "", code: newCodeName, children: []}, ...child};
console.log('adding child ', child);
parent.children = [...parent.children, child];
}
function findInHouseList(houseList,code) {
for (let house of houseList) {
let foundElement = findElement(house,code);
if ( foundElement)
return foundElement;
}
}
function findElement(currentElement, code) {
if ( currentElement.code === code)
return currentElement;
if (currentElement.children?.length > 0)
{
for (let child of currentElement.children) {
let foundElement = findElement(child,code);
if ( foundElement)
return foundElement;
}
}
return null;
}
I decided to let the code manage the code names for new children. It seems the easiest.
What you're trying to do is updating a JSON value at a dynamic path.
This function will append a child to the item which holds the specified code.
You may add conditions to check if the item at the code is defined
function appendChild(houses, code, item) {
let path = code.split('')
let o = houses
for (let i = 0; i < path.length; i++) {
let n = path[i] - 1
o = o[n]["children"]
}
o.push(item)
return houses
}
However, you should start your code indexes at 0 and storing them inside the JSON is useless since they are simply the path to reach the item.
I want to assign a new Value (let say this is a flag such as isActive) from an existing object. this is an example for the object I'm using to try:
let localValue = {
"id": "019eadd3-2e71-4446-a195-69d849d88a43",
"discount": {
"code": "PFMQWERTY",
"id": "019eadd3-2e71-4446-a195-69d849d88a43",
"isActive": false
},
"discountId": "019eadd3-2e71-4446-a195-69d849d88a43",
"discountRules": [
{
"id": "1-1",
"type": "FIXED",
"value": 30000,
"package": {
"id": "1-1-A",
"name": "Package A",
"maxDiscountInApps": 3,
"discountInApps": [
{
"id": "1-1-A-A",
"code": "QWERTY",
"expirationDate": "2034-02-28T00:00:00+0000"
}
]
}
},
{
"id": "1-2",
"type": "FIXED",
"value": 100000,
"package": {
"id": "1-2-A",
"name": "Package B",
"maxDiscountInApps": 3,
"discountInApps": [
{
"id": "1-2-A-A",
"code": "KASH",
"expirationDate": "2032-02-03T00:00:00+0000"
}
]
}
},
{
"id": "1-3",
"type": "FIXED",
"value": 15000,
"package": {
"id": "1-3-A",
"name": "Package C",
"maxDiscountInApps": 3,
"discountInApps": []
}
},
{
"id": "1-4",
"type": "FIXED",
"value": 180000,
"package": {
"id": "1-4-A",
"name": "Package D",
"maxDiscountInApps": 3,
"discountInApps": []
}
},
{
"id": "1-5",
"type": "FIXED",
"value": 15000,
"package": {
"id": "1-5-A",
"name": "",
"maxDiscountInApps": 3,
"discountInApps": []
}
},
{
"id": "1-6",
"type": "FIXED",
"value": 30003,
"package": {
"id": "1-6-A",
"name": "Package E",
"maxDiscountInApps": 3,
"discountInApps": [
{
"id": "1-6-A-A",
"code": "QWERTY",
"expirationDate": "2034-02-28T00:00:00+0000"
},
{
"id": "1-6-A-B",
"code": "KASH",
"expirationDate": "2032-02-03T00:00:00+0000"
},
{
"id": "1-6-A-C",
"code": "ANT",
"expirationDate": "2021-07-30T00:00:00+0000"
}
]
}
},
{
"id": "1-7",
"type": "FIXED",
"value": 5000,
"package": {
"id": "1-7-A",
"name": "Package F",
"maxDiscountInApps": 3,
"discountInApps": []
}
}
],
"expirationDate": "28/02/2034 07:00:00",
"totalPackagesShown": 2
}
the goals I want to achieve is to check if there is the same code in discountRules.package.discountInApps.code === this.localValue.discount.code then return true, if failed then return false.
I can already find the way to set it using map() and some() like this:
this.localValue.discountRules = this.localValue.discountRules.map(
rule => ({
...rule,
isActive:
rule.package &&
rule.package.discountInApps &&
rule.package.discountInApps.length !== 0
? rule.package.discountInApps.some(
ruleItems =>
ruleItems.code === this.localValue.discount.code
)
: false
})
);
but performance wise, is it better using map() and reducer() combination for this case or better stay using map() and some()? because I read it in here Array.prototype.reduce() it seems when using reducer can make an array reduce until it finds a value that I want (is my understanding correct?) so if it's true then...
is it better using this map() and reducer() (if its possible) or stay with map() and some() combination?
(I'm still failed to implement map() and reducer(), so can someone tell me how to use this (map() and reducer()) combination?)
Notes:
if by any chance there is a better way, I'm open for it
just in case, I'm already try to read this thread but still not quite understand as how to implement it in my case:
remove-object-from-array-using-javascript
If you prefer performance, the traditional for loop would be the fastest.
For execution times, I get these
Map & Some: 27ms average
Map & Reduce: 32ms average
You can use console.time() and console.timeEnd() to check for execution times.
The array Reduce method will run a callback function on each element of the supplied array and will return the calculated value from the callback (the value will be stored in the index of the element). If you want to use reduce with map, you can do something like this
localValue.discountRules = localValue.discountRules.map((rule) => ({
...rule,
isActive:
rule.package &&
rule.package.discountInApps &&
rule.package.discountInApps.length !== 0
? rule.package.discountInApps.reduce(
(accumulatedValue, currentValue) =>
accumulatedValue && currentValue.code === localValue.discount.code,
true // this is the default initial value for the accumulatedValue
)
: false,
}));
Alternatively, you can use optional chaining (?.) Like this
localValue.discountRules = localValue.discountRules.map((rule) => ({
...rule,
isActive:
rule?.package?.discountInApps?.some(
(ruleItems) => ruleItems.code === localValue.discount.code
)
}));
(Do check out the supported browsers here).
This question already has answers here:
Extract certain properties from all objects in array
(5 answers)
Closed 1 year ago.
I am trying to filter selected property from object using JavaScript.
This is my array
const odata=[
{
"id": "0001",
"type": "donut",
"name": "Cake",
"ppu": 0.55,
},
{
"id": "0002",
"type": "ansd",
"name": "EARK",
"ppu": 0.67,
}
];
I want output like this - I want to select only 2 (id,type) props from the object
[
{"id": "0001","type": "donut"}
{"id": "0002","type": "ansd"}
]
We can use Array.map and some Destructuring to get the desired result.
The destructuring assignment syntax allows us to get selected values from Objects and Arrays in a convenient way.
const odata= [ { "id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55, }, { "id": "0002", "type": "ansd", "name": "EARK", "ppu": 0.67, } ];
const result = odata.map(({ id, type}) => ({ id, type }));
console.log("Result:", result)
User Array.prototype.map() for generating a new array from an existing one.
Reference
const odata = [
{ "id": "0001", "type": "donut", "name": "Cake", "ppu": 0.55 },
{ "id": "0002", "type": "ansd", "name": "EARK", "ppu": 0.67 }
];
const output = odata.map(node => ({
id: node.id,
type: node.type,
}))
console.log(output)
For reference I have zero javascript knowledge or any coding knowledge. I typically just hook up applications via IPASS applications that don't require any coding knowledge. However, I found out I need to inject some javascript into the application in order to avoid an error message.
I have the below JSON record.
I need to get rid of the empty array (sorry... if it is not an array but an object? Like I said, no javascript knowledge).
In the below code essentially what I want is to completely delete this line, because there is nothing inside the brackets and it is causing errors:
"lineitemsdata": []
Full JSON record below for reference
"id": "5399286500",
"properties": {
"state": "AB",
"website": null,
"zip": "T3B5Y9"
},
"createdAt": "2021-02-18T22:13:06.111Z",
"updatedAt": "2021-05-17T14:35:09.540Z",
"archived": false,
"associations": {
"deals": {
"results": [
{
"id": "5230410841",
"type": "company_to_deal"
}
]
}
},
"dealdata": [
{
"id": "5230410841",
"properties": {
"hs_lastmodifieddate": "2021-05-13T14:00:33.101Z",
"hs_object_id": "5230410841",
"hubspot_owner_id": "52200226"
},
"associations": {
"line items": {
"results": [
{
"id": "1468189759",
"type": "deal_to_line_item"
},
{
"id": "1468189760",
"type": "deal_to_line_item",
"lineitemsdata": []
}
]
}
}
}
],
"DealOwner": [
{
"id": "52200226",
"email": "email#email.com",
"firstName": "Bob"
}
],
"NetSuiteCustomerID": 1745
}
Item inside object is called a property. If you (for some reason) have to include the property, but don't want it to have any value you can either set it's value to null or undefined.
I suspect I'm going to get criticized for this, but here is a quick and dirty way of removing this specific problem through string replacement. The 'right' way would be to break down your json into separte objects until you get to the level where the offending object lives, remove it, then rebuild it all back. For what it's worth, here's an alternative to that
let json = {
"id": "5399286500",
"properties": {
"state": "AB",
"website": null,
"zip": "T3B5Y9"
},
"createdAt": "2021-02-18T22:13:06.111Z",
"updatedAt": "2021-05-17T14:35:09.540Z",
"archived": false,
"associations": {
"deals": {
"results": [{
"id": "5230410841",
"type": "company_to_deal"
}]
}
},
"dealdata": [{
"id": "5230410841",
"properties": {
"hs_lastmodifieddate": "2021-05-13T14:00:33.101Z",
"hs_object_id": "5230410841",
"hubspot_owner_id": "52200226"
},
"associations": {
"line items": {
"results": [{
"id": "1468189759",
"type": "deal_to_line_item"
},
{
"id": "1468189760",
"type": "deal_to_line_item",
"lineitemsdata": []
}
]
}
}
}],
"DealOwner": [{
"id": "52200226",
"email": "email#email.com",
"firstName": "Bob"
}],
"NetSuiteCustomerID": 1745
}
json = JSON.stringify(json)
let strstart = json.indexOf('"lineitemsdata":[]');
let commapos = json.lastIndexOf(',', strstart);
json = json.substr(0, commapos) + " " + json.substr(commapos + 1);
json = json.replace('"lineitemsdata":[]', '');
json = JSON.parse(json)
console.log(json)
You can use this to strip any empty lineitems arrays from your json.
Assuming the reference to your record is json
for(dealIdx in json.dealdata) {
for (resultIdx in json.dealdata[dealIdx].associations["line items"].results) {
let lineItemsData = json.dealdata[dealIdx].associations["line items"].results[resultIdx].lineitemsdata
if (lineItemsData != undefined && lineItemsData.length === 0 ) {
delete json.dealdata[dealIdx].associations["line items"].results[resultIdx].lineitemsdata
}
}
}
For each object inside this array containing userHandle array loop through that array(userHandle one) and check if one of those values matches some string I choose called uid. How to write that code in Javascript?
Array [
Object {
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
Object {
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": true,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
"userHandle": Array [
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
"LrIwIx9I1xQBJ7aeCSrinpEaDP53",
],
}]
Try this code:
var uid = "LrIwIx9I1xQBJ7aeCSrinpEaDP53";
yourArray.forEach(function(item, _){
return item['userHandle']?.indexOf(uid);
});
The '?' is to make sure your Object contains the 'userHandle' property
This is the function you need... and below you can see how to use it.
You need to pass the value you are looking for, and the array with the information.
function findInUserHandle(uidValue, array)
{
return array.reduce
(
(acum, current) =>
current.userHandle && current.userHandle.indexOf(uidValue) !== -1 || acum,
false
)
}
let array = [
{
"avatar": null,
"hugCount": 2,
"id": 35,
"liked": false,
"name": "fhfdhdhf",
"text": "Yoho",
"timestamp": 1610471860157,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
},
{
"avatar": null,
"hugCount": 1,
"id": 34,
"liked": true,
"mood": 2,
"name": "fhfdhdhf",
"text": "I'm fine today.",
"timestamp": 1607943705709,
"uid": "FOgepuJqxXfkHxI8OAV2KMWodXo1",
"userHandle":[
"Aw8AUj1mPkON1Fd1s6LhkNETHfb2",
"LrIwIx9I1xQBJ7aeCSrinpEaDP53",
],
}
]
findInUserHandle('something', array) //? false
findInUserHandle('Aw8AUj1mPkON1Fd1s6LhkNETHfb2', array) //? true
findInUserHandle('mood', array) //? false