Destructing assignment javascript doesnt work [duplicate] - javascript

This question already has answers here:
How to delete property from spread operator?
(9 answers)
Closed 2 years ago.
I've tried to destruct a json. This is the original:
const shoppingLists = [
{
id: 0,
name: "empty shopppinglist",
location: "",
targetDate: "",
priority: "",
isFinished: false,
items: [{
name: ""
}]
},
{
id: 1,
name: "full shopppinglist",
location: "migros",
targetDate: "",
priority: "1",
isFinished: true,
items: [{
name: "apfel"
}]
}}
I need now just the lists with the elements but without the items list
const { id, name, location, targetDate, priority, isFinished } = shoppingLists
res.send(shoppingLists)
But when I receive/log shoppingLists, I always get again the whole object.
I've also tried with items, ...rest but same result at the end, what am I doing wrong?

You should change your syntax since shoppingLists is an array:
const { id, name, location, targetDate, priority, isFinished } = shoppingLists[0]
Also, if you want to remove an item from an array you definitely need to use splice or if you want to remove the first element and then get its value as return then you should use shift.
const { id, name, location, targetDate, priority, isFinished } = shoppingLists.shift()

Related

Javascript function that merges objects based on values of the keys and restructures them based on values of the keys

I am trying to write a javascript function that receives at least two parameters - array of objects and empty nested object.
Array of objects contain objects that are not nested. All of them have same keys, but some keys might have different values. Each key name is something like "primary key" on certain level of nesting. Where the key should hold place as "primary key" is defined by empty nested object.
Empty nested object defines which key is "primary key" for which level of nesting. It defines the structure we need the final merged object to be.
The function should find and merge together all objects in array of objects, that have same value for the key thats first in empty nested object AND is type of object. However, because the objects hold other keys that have the same name but might have different values, if merged instantly, we would lose the different values.
So it takes value of last key that was found in empty nested object and was type of object, and creates a new key with name of that value and makes it a object. Inside it, it creates the name of key that this object is from, creates the key with same name and assigns it that value.
Then it keeps doing the same, based on empty nested object. In other words, the function is keep looking on empty nested object and checks if on the current level there is any other key thats type of object, before merging all objects together. It is merging the keys with same values from the bottom up.
All keys dont necessarily have to be "primary keys" on some level. These keys are present inside "DATA" level. In "DATA" might also appear a key that was a "primary key" on some level. Again, this is defined by empty nested object.
Example of empty nested object:
{
PERSON: {
CRT: {
CRT_VALUE: {
CRT: null,
CODE: {
CODE_VALUE: {
CODE: null,
DATA: {
CODE: {
VALUE: null,
META: null,
NAME: null
},
NAME: {
VALUE: null,
META: null,
NAME: null
},
SUM: {
VALUE: null,
META: null,
NAME: null
},
CONTEXT: {
VALUE: null,
META: null,
NAME: null
}
}
}
}
}
}
}
}
Example of array of objects:
[
{
PERSON: "21",
CODE: "CMSS",
CONTEXT: "",
NAME: "SALARY",
CRT: "Common",
SUM: 162000
},
{
PERSON: "21",
CODE: "DOS",
CONTEXT: "",
NAME: "TAX",
CRT: "Common",
SUM: 192000
},
{
PERSON: "21",
CODE: "UPL",
CONTEXT: "",
NAME: "WAGE",
CRT: "Other",
SUM: 255000
},
{
PERSON: "22",
CODE: "CMSS",
CONTEXT: "",
NAME: "SALARY",
CRT: "Common",
SUM: 150000
}
]
The final array of objects should be merged based on values of the keys and based on empty nested object.
For given examples, the final array of objects should look like this:
[
{
PERSON: "21",
CRT: {
"Common": {
CRT: "Common",
CODE: {
"CMSS": {
CODE: "CMSS",
DATA: {
NAME: {
VALUE: "SALARY",
META: undefined,
NAME: "NAME",
},
SUM: {
VALUE: 162000,
META: undefined,
NAME: "SUM",
},
CONTEXT: {
VALUE: "",
META: undefined,
NAME: "CONTEXT",
},
CODE: {
VALUE: "CMSS",
META: undefined,
NAME: "CODE",
}
}
},
"DOS": {
CODE: "DOS",
DATA: {
NAME: {
VALUE: "TAX",
META: undefined,
NAME: "NAME",
},
SUM: {
VALUE: 192000,
META: undefined,
NAME: "SUMA",
},
CONTEXT: {
VALUE: "",
META: undefined,
NAME: "KONTEXT",
},
CODE: {
VALUE: "DOS",
META: undefined,
NAME: "CODE",
}
}
}
},
},
"Other": {
CRT: "Other",
CODE: {
"UPL": {
CODE: "UPL",
DATA: {
NAME: {
VALUE: "WAGE",
META: undefined,
NAZEV: "NAME",
},
SUM: {
VALUE: 255000,
META: undefined,
NAZEV: "SUM",
},
CONTEXT: {
VALUE: "",
META: undefined,
NAME: "CONTEXT",
},
CODE: {
VALUE: "UPL",
META: undefined,
NAME: "CODE",
}
}
}
}
}
}
},
{
PERSON: "22",
CRT: {
"Common": {
CRT: "Common",
CODE: {
"CMSS": {
CODE: "CMSS",
DATA: {
NAME: {
VALUE: "SALARY",
META: undefined,
NAME: "NAME",
},
SUM: {
VALUE: 150000,
META: undefined,
NAME: "SUM",
},
CONTEXT: {
VALUE: "",
META: undefined,
NAME: "CONTEXT",
},
CODE: {
VALUE: "CMSS",
META: undefined,
NAME: "CODE",
}
}
}
}
}
}
}
]
The function should be generic, so it works for any given array of objects, and any given empty nested object - however, empty nested object must always have defined structure by the key names.
The array of objects must (will) always contain all the needed keys based on empty nested object.
What I tried and did not work:
const mergeObjectsByKey = (array, key, newObject = {}, level = 1) => {
let newObjects = []
array.forEach(obj => {
let currentObject = newObject;
for (let k of Object.keys(key)) {
if (typeof key[k] === 'object') {
if (obj.hasOwnProperty(k)) {
if (!currentObject.hasOwnProperty(obj[k])) {
currentObject[obj[k]] = {};
}
currentObject = currentObject[obj[k]];
mergeObjectsByKey([obj], key[k], currentObject, level + 1);
}
} else {
if (Object.keys(key)[Object.keys(key).length - 1] === k) {
currentObject["HODNOTA"] = obj[k];
currentObject["META"] = null;
currentObject["NAZEV"] = k;
} else {
if (!currentObject.hasOwnProperty(k)) {
currentObject[k] = obj[k];
}
}
}
}
newObjects.push(newObject);
});
return newObjects;
}
newObject - the object that will be returned as the final object
level - a number that keeps track of the current level of nesting in the key object. It is used to determine if the current key in the empty nested object is a parent or child key
The function loops through each key in the empty nested object. If the current key is an object, it loops through each object in the array of objects and checks if the object has a key with the same name as the current key. If it does, it calls the function recursively with the current object, current key and current level+1 as the parameters. By doing this, it will check the next level of key object and compare it with the next level of the array of objects.
In the next level, it will again check if the key is an object or not. If it is an object, it will check if the key is already present in the current object or not. If it is not present, it will create a new property with the key and make it equal to an empty object.
Then it will call the function recursively with the current object, current key, and current level+1 as the parameters. If the key is not an object, it will check if it is the last key of the key object or not.
If it is the last key, it will add three properties HODNOTA, META and NAZEV to the current object.
If it is not the last key, it will add the key to the current object and make it equal to an array of values of the same key in the array of objects.
What I expected:
the function will return final merged and structured objects in an array
What I got:
array of objects of objects. Each object in array contain same number of objects, and all these objects in the array are same.
Inside objects of the array, each object has the name of value of "PERSON" that was used to merging.
In each PERSON object, there are objects named by all CRT values found for that PERSON value. Each CRT object is then empty.
I can see that partially it was merged succesfully, but from CRT the merging failed and lost the data.
Not sure it's perfect, but it does something close. The technique here starts with Object.fromEntries(Object.entries(obj).map(...)) to modify the keys and values and build a new object based on the template object.
const TPL = {PERSON:null,CRT:{CRT_VALUE:{CRT:null,CODE:{CODE_VALUE:{CODE:null,DATA:{CODE:{VALUE:null,META:null,NAME:null},NAME:{VALUE:null,META:null,NAME:null},SUM:{VALUE:null,META:null,NAME:null},CONTEXT:{VALUE:null,META:null,NAME:null}}}}}}};
const values = [{PERSON:"21",CODE:"CMSS",CONTEXT:"",NAME:"SALARY",CRT:"Common",SUM:162000},{PERSON:"21",CODE:"DOS",CONTEXT:"",NAME:"TAX",CRT:"Common",SUM:192000},{PERSON:"21",CODE:"UPL",CONTEXT:"",NAME:"WAGE",CRT:"Other",SUM:255000},{PERSON:"22",CODE:"CMSS",CONTEXT:"",NAME:"SALARY",CRT:"Common",SUM:150000}];
function fillTpl(tpl, values, parentKey = '') {
return Object.fromEntries(Object.entries(tpl).map(([k, v]) => {
if (k.endsWith('_VALUE')) k = values[k.slice(0, -6)];
if (v == null) v = (k === 'VALUE') ? values[parentKey] : values[k];
else v = fillTpl(v, values, k);
return [k, v];
}));
}
console.log(values.map(vals => fillTpl(TPL, vals)));
If you want to add new properties to the object, you can do like Object.fromEntries(Object.entries(obj).flatMap(([k, v]) => [[k, v], [k+'_2', v]]))

Filter nested array in object based on specific values of another array [duplicate]

This question already has answers here:
Filter array of objects based on another array in javascript
(10 answers)
Closed 7 months ago.
I have an array of Objects, and every object has an array of strings (tags), I need to filter the array of objects based on another array.
data: [
{
"id":"Nerium",
"tags":["CMS Selection", "Experience Design", "Development","UX"],
"featured":0
},
{
"id":"WesternDigital",
"tags":["Digital Strategy", "Analytics", "Example"],
"featured":1
},
{
"id":"Example",
"tags":["Example", "Analytics", "UX"],
"featured": 0,
},
I need to filter the above data based on an Array like this:
activeTags: ['UX', 'Example']
And the objects of Data I filter need to specifically have the values inside activeTags, in this case if for example an Object has 'UX' but it doesn't have 'Example', I don't return it.
Expected output:
data: [{
"id": "Example",
"tags": ["Example", "Analytics", "UX"],
"featured": 0,
}]
Or it should return every Object that has tags that specifically have the values in activeTags
This should work
const data = [
{
id: "Nerium",
tags: ["CMS Selection", "Experience Design", "Development", "UX"],
featured: 0,
},
{
id: "WesternDigital",
tags: ["Digital Strategy", "Analytics", "Example"],
featured: 1,
},
{
id: "Example",
tags: ["Example", "Analytics", "UX"],
featured: 0,
},
];
const activeTags = ["UX", "Example"];
const filtered = data.filter(({ tags }) =>
activeTags.every((tag) => tags.includes(tag))
);
console.log(filtered);
you can use .every to check that the object has all the active tags
I haven't tested, but I think the following should work:
const result = data.filter( record =>
activeTags.every( tag =>
record.tags.includes( tag )
)
);
filter() returns array with only elements that pass its function test. every() returns true only if every element passes its function test. includes() will test if the element is included in the record.tags array.

Check if an array of object is exactly equal to another array that contains one of its property [duplicate]

This question already has answers here:
Check if an array contains any element of another array in JavaScript
(32 answers)
Closed 1 year ago.
I have these 2 arrays
The first one is fixed and does not change and contains the id of the 2nd array:
fixed=["123","456","789"]
The second can change
variableArray=[{name:"Joe",id:"123"},{name:"Joe",id:"456"},{name:"Joe",id:"789"}]
I want to return true if, even if there were some changes at the end the variable array is the same length and contains exactly the same keys of the "fixed"
NOT VALID:
fixed=["123","456","789"]
variableArray=[{name:"Joe",id:"456"},{name:"Joe",id:"789"}]
return false because is missing the id "123" (and the length is also different so is excluded by default)
NOT VALID:
fixed=["123","456","789"]
variableArray=[{name:"Joe",id:"123"},{name:"Joe",id:"456"},{name:"Joe",id:"001"}]
this will return false because, even if contains 3 elements as there are in the "fixed" is missing the id "789" and have another "001" instead
as #mplungjan mentiond, you can use Every:
let fixed = ["123", "456", "789"];
let variableArray1 = [{
name: "Joe",
id: "123"
}, {
name: "Joe",
id: "456"
}, {
name: "Joe",
id: "789"
}];
let variableArray2 = [{
name: "Joe",
id: "123"
}, {
name: "Joe",
id: "456"
}, {
name: "Joe",
id: "001"
}]
let containsAll1 = variableArray1.every(elem => fixed.includes(elem.id));
let containsAll2 = variableArray2.every(elem => fixed.includes(elem.id));
console.log(containsAll1, containsAll2);

Trying to create array of strings to use in a destructuring function for removing object properties, only single string value works

I have an array of objects as part of a data response that I am grouping together using lodash's groupBy via each object's groupName key.
Some of the items that come back have a groupName value of null, undefined or an empty string and lodash creates separate groups for each of those values.
I combine all of the falsey groups into a single group name "Uncategorized" and attempt to remove the original falsey groups to only return "Uncategorized" and all other truthy groups.
The problem I'm running into is that I'm trying to use the rest operator to remove the original falsy objects with undefined, null, and empty string keys by assigning them to a variable like let groupKeysToRemove = ['undefined', 'null', ''] and then trying to remove them like let { [groupKeysToRemove]: removed, ...groups } = initialGroups; but it returns the same Object with nothing removed. I'm not sure if my syntax is wrong or what but I am stumped.
Code via sandbox:
const resources = [
{
groupName: undefined,
name: "color organizer"
},
{
groupName: null,
name: "Bart_Simpson_200px"
},
{
groupName: "Spread Sheets",
name: "Backflow"
},
{
groupName: "Spread Sheets",
name: "220px-Marge_Simpson"
},
{
groupName: "",
name: "212px-Homer_Simpson_2006"
},
{
groupName: "Spread Sheets",
name: "Product 6"
},
{
groupName: "Warranties",
name: "Warranty Bart Simpson"
},
{
groupName: "Warranties",
name: "Warranty Product 2"
},
{
groupName: "Warranties",
name: "Warranty Product 3"
}
];
let initialGroups = groupBy(resources, "groupName");
let uncategorizedGroups = [];
uncategorizedGroups.push(...initialGroups[undefined], ...initialGroups[null], ...initialGroups[""]);
const renameGroups = uncategorizedGroups.map((object) => {
object.groupName = "Uncategorized";
return object;
});
const renamedGroups = groupBy(renameGroups, "groupName");
console.log('RENAMED GROUPS: ', renamedGroups)
const groupKeysToRemove = "undefined"
let { [groupKeysToRemove]: removed, ...groups } = initialGroups;
groups = { ...groups, ...renamedGroups };
Think of the brackets syntax [] for the destructing operation as an index to a property of an object, not an array that you pass in. It's analogous to calling for example obj["a"] vs obj.a to access the a field on obj.
So knowing this, you need to pass in 3 arguments to extract the values that you want to remove. For null and undefined I had to put them in separate variables, it wasn't working when putting them directly in the brackets:
const nullKey = null;
const undefinedKey = undefined;
let {
[nullKey]: nullGroup,
[undefinedKey]: undefinedGroup,
[""]: emptyStringGroup,
...groups } = initialGroups;
groups = { ...groups, ...renamedGroups };
console.log("initialGroups: ", initialGroups);
console.log("GROUPS: ", groups);
console.log("null group", nullGroup)
console.log("undef group", undefinedGroup)
console.log("emptyStringGroup group", emptyStringGroup)

Having trouble extracting value from Javascript object's multidimensonal array [duplicate]

This question already has answers here:
How can I access and process nested objects, arrays, or JSON?
(31 answers)
Closed 6 years ago.
I'm attempting to use Javascript objects to work with some data. Here is the object itself (parsed from JSON) which is defined as accounts:
{
startIndex: 0,
pageSize: 20,
pageCount: 1,
totalCount: 1,
items: [
{
id: 123456,
emailAddress: 'test#test.com',
userName: 'test#test.com',
firstName: 'John',
lastName: 'Hancock',
customerSet: 'default',
commerceSummary: [
Object
],
contacts: [
Object
],
userId: '92834439c29389fj292',
notes: [
],
attributes: [
Object
],
segments: [
Object
],
taxExempt: false,
externalId: '2100010368',
isAnonymous: false,
auditInfo: [
Object
],
isLocked: false,
isActive: true,
hasExternalPassword: false,
customerSinceDate: 2016-06-23T18: 26: 46.000Z
}
]
}
While I can retrieve accounts.items without issue, I'm having some trouble retrieving individual values such as id or emailAddress from the item itself. Doing accounts.items[id] or accounts.items[emailAddress] does not work but I believe it's due to the fact that items can be more than 1 so I should be specifying the "first result" for items from that list. If that is the case, how do I retrieve the emailAddress or id for the first items array? The desired result from the above JSON object should be "123456" if id and "test#test.com" if email. Thanks in advance.
Your items is an array. You have to fetch data from it by indexes (like items[0]). If you are looking for an item, with their properties, use Array.find method.
The find method executes the callback function once for each element
present in the array until it finds one where callback returns a true
value. If such an element is found, find immediately returns the value
of that element. Otherwise, find returns undefined. callback is
invoked only for indexes of the array which have assigned values; it
is not invoked for indexes which have been deleted or which have never
been assigned values.
var accounts = {
startIndex: 0,
pageSize: 20,
pageCount: 1,
totalCount: 1,
items: [
{
id: 123456,
emailAddress: 'test#test.com',
userName: 'test#test.com',
firstName: 'John',
lastName: 'Hancock',
customerSet: 'default'
}
]
};
var sampleAccount = accounts.items.find(function (item) {
return item.id == 123456;
});
if (sampleAccount) {
console.log(sampleAccount.emailAddress);
}
You are right, first you need to reference the first element of the array. Then you can query its properties.
For example, to get the ID and email address of the first item you would write
accounts.items[0].id
accounts.items[0].emailAddress
Arrays elements start at index 0 in JavaScript, so the first element of the array has index 0, the second 1, and so on.
Items is an array and emailAddress is a Key, then you can get the value using:
accounts.items[0].emailAddress

Categories

Resources