how to read values of nested objects with predefined string [duplicate] - javascript

This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 3 years ago.
i have objects which have hold x amounts of nested objects:
let obj = {
nestedObject: {
key: value
}
}
or
let obj2 = {
nestedObject2: {
nestedObject3: {
key2: value2
}
}
}
etc.
Getting the values of both those objects is not that difficult:
obj.nestedObject.key
obj['nestedObject']['key]
or
obj2.nestedObject2.nestedObject3.key2
obj2['nestedObject2']['nestedObject3']['key2']
This should happen dynamically though which is what I don't know how to achieve.
I get random objects with the structure above and also a string which tells me where to find the values. For obj2 in the example above I would get the string
"nestedObject2.nestedObject3.key2"
How do I use this information to get the proper value? The two strategies above don't work anymore and something easy like
obj2['nestedObject2.nestedObject3.key2']
doesn't work unfortunately.

You can split the string by the delimiter of a period character, and then reduce to find the appropriate property, going down a level on every iteration.
str.split(".").reduce((a, v) => (a = a[v], a), parent_object);
let o = {
nestedObject2: {
nestedObject3: {
key2: "a key"
}
}
},
str = "nestedObject2.nestedObject3.key2";
let ref = str.split(".").reduce((a, v) => (a = a[v], a), o);
console.log(ref);

Related

Check uniqueness with in nested object property values in array of objects [duplicate]

This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 1 year ago.
I am returning null if an array of objects has the same property values and is fine with the direct object properties. I am trying with nested object property values in the same array, but it is failing. Below is the code for the same.
const getNullOrUniquePropertyValue = (arrToCheck, keyName, includeFullObject = null) => {
const uniqueValues = [...new Set(arrToCheck.map((v) => v[keyName]))];
if (uniqueValues.size !== 1) {
return null;
}
return includeFullObject ? arrToCheck[0].includeFullObject : arrToCheck[0].keyName;
};
And I am calling above function like as below
getNullOrUniquePropertyValue(
spaces,
'designHubProjectSpaceTypeId'
)
I am getting results as null for the above function because designHubProjectSpaceTypeId is not the same in the array.
I am passing nested objects property like as below, and it is returning null for below condition even if the array has both same values.
getNullOrUniquePropertyValue(spaces, 'spaceGeometry.ceilingHeight')
and the space structure like this as below
"spaces": [
{
"spaceGeometry": {
"ceilingHeight": 9
},
"designHubProjectSpaceTypeId": "some Id"
},
{
"spaceGeometry": {
"ceilingHeight": 9
},
"designHubProjectSpaceTypeId": "some other Id"
}
]
Could anyone please let me know where I am doing wrong with the above code?
Many thanks in advance!!
Some feedback:
v[keyName] isn't going to work if keyName is a string with a dot ("spaceGeometry.ceilingHeight"), you'll have to split the string and lookup the value at each level manually
uniqueValues is an array not a set, so use .length instead of .size
I made a simple function getNestedValue() that uses reduce to extract a nested value from an object.
const spaces = [
{
"spaceGeometry": {
"ceilingHeight": 9
},
"designHubProjectSpaceTypeId": "some Id"
},
{
"spaceGeometry": {
"ceilingHeight": 9
},
"designHubProjectSpaceTypeId": "some other Id"
}
];
const getNestedValue = (obj, path) => path.split(".").reduce((accum, key) => accum[key], obj);
const getNullOrUniquePropertyValue = (arrToCheck, keyName) => {
const uniqueValues = [...new Set(arrToCheck.map((v) => getNestedValue(v, keyName)))];
if (uniqueValues.length !== 1) {
return null;
}
return uniqueValues[0];
};
const result = getNullOrUniquePropertyValue(
spaces,
'spaceGeometry.ceilingHeight'
);
console.log(result);
I omitted includeFullObject from my example because it's not relevant to this particular issue, and I'm unclear what it's supposed to do. If you're having issues with that part too, let me know the details and I can help.

How to remove dublicate values from array of objects using javaScript? [duplicate]

This question already has answers here:
Get all unique values in a JavaScript array (remove duplicates)
(91 answers)
Closed 1 year ago.
I have this array of objects, my aim is to remove dublicate values from values array, I want the result to be [{name:'test1', values:['35,5', '35,2','35,3']}, {name:'test2', values:['33,2', '34,3', '32,5']}]
I have tried following solution but it does not works, Do you have any suggestions? Thanks in advance
let arr = [{name:'test1', values:['35,5', '35,2', '35,2', '35,3', '35,5']},
{name:'test2', values:['35,1', '35,1', '33,2', '34,3', '32,5']}]
let uniqueArray = arr.values.filter(function(item, pos) {
return arr.values.indexOf(item.values) == pos;
})
console.log(uniqueArray)
}
}
You can easily remove duplicates from an Array by creating a new Set based off it.
Set objects are collections of values. You can iterate through the elements of a set in insertion order. A value in the Set may only occur once; it is unique in the Set's collection
If you want the result in an array, just use spread syntax for that, for example:
let arr = [{
name: 'test1',
values: ['35,5', '35,2', '35,2', '35,3', '35,5']
},
{
name: 'test2',
values: ['35,1', '35,1', '33,2', '34,3', '32,5']
}
];
const uniqueArr = arr.reduce((accum, el) => {
// Copy all the original object properties to a new object
const obj = {
...el
};
// Remove the duplicates from values by creating a Set structure
// and then spread that back into an empty array
obj.values = [...new Set(obj.values)];
accum.push(obj);
return accum;
}, []);
uniqueArr.forEach(el => console.dir(el));

Get random value from JSON using ONLY parse and Math.random WITHOUT loops, arrays and Object.keys [duplicate]

This question already has answers here:
Pick random value from JSON property
(3 answers)
Closed 2 years ago.
I have got a JSON:
let jsonName = '{"name1": "John", "name2": "Billy", "name3": "Tristan"}';
let jsonSurname = '{ "surname1": "Doe", "surname2": "Smith", "surname3": "Dodson"}';
I need to get random value from both jsonName, jsonSurname (for example "John" and "Doe") and parse this two values into one object.
I must to use Math.random. There can't be loops, arrays, Object.keys, Object.entries, Object.values, Object.getOwnPropertyNames.
I think that i must to use parse somehow for both properties:
JSON.parse(jsonName, function (key, value) {
// SOME MAGIC with Math.random
});
Help me please!
If you know that every property in jsonName starts with name followed by a number, you could use string literals to access a specific property.
Example:
const data = {
name1: 'vitor',
name2: 'roberto',
name3: 'joao'
}
console.log(data[`name${1}`]) // output: 'vitor'
With that, all you have to do is use Math.random() to generate the random number.
For example, to generate a random number from 1 to 10, you could use:
Math.floor(Math.random() * 10) + 1
Assign it to a variable:
const randomNumber = Math.floor(Math.random() * 10) + 1
Then use it in the string literal:
console.log(data[`name${randomNumber}`])
Wow, this was a fun challenge!
The restrictions pose a few major obstacles. A double-lookup is absolutely unavoidable because you need to know the number of possible names which is unavailable until the object has finished parsing - and because arrays, Object.keys, etc, are not allowed, you can't then look up the answer.
I've made a few assumptions here:
We don't already know the number of entries
We can't depend on the keys being in the same format and reliable (name1, name2, etc)
We want to avoid manually parsing the json strings, and avoid parsing them twice
First thought: The obvious answer is to parse the data twice. But this is ugh.
Next thought: The approach says that arrays are not allowed, but strings are technically arrays - this could be abused in order to cheat an answer.
But wait.. we can't use arrays, but we can use objects - and with implicit type coersion, objects can be accessed with numeric indices.
So let's go.
const jsonName = '{"name1": "John", "name2": "Billy", "name3": "Tristan"}';
const jsonSurname = '{ "surname1": "Doe", "surname2": "Smith", "surname3": "Dodson"}';
function pick(source, callback)
{
let chosen;
const tempObject = {};
let count = 0;
JSON.parse(source, function (key, value)
{
if (typeof value === 'object')
{
return callback(chosen);
}
tempObject[count] = value;
count++;
chosen = tempObject[Math.floor(Math.random() * count)];
});
}
pick(jsonName, (firstName) => {
pick(jsonSurname, (lastName) => {
const result = { 'name': firstName, 'surname': lastName};
console.log(result);
});
})
Of course, JSON.parse itself invokes several loops, but I guess this is OK.

How to create a prefilled array of defined length? [duplicate]

This question already has answers here:
Strange behavior of an array filled by Array.prototype.fill()
(9 answers)
Closed 3 years ago.
I am trying to create an array which has a defined length and fill it with empty arrays. I've tried using all possibilities given by #stpoa's answer here but my array does not behave correctly.
Given the code (I simplified it for the sake of example):
const tasksArray = Array(3).fill([])
const tasksArray2 = [[], [], []]
const tasks = ['task1', 'task2']
const fillWithData = (array) => {
tasks.forEach(task => {
array[0].push(task)
})
}
Gives me an incorrect output for tasksArray and a obviously a correct one for tasksArray2 which is hardcoded
fillWithData(tasksArray) // [['task1', 'task2'], ['task1', 'task2'], ['task1', 'task2']] => not OK, duplicates values!
fillWithData(tasksArray2) // [['task1', 'task2'], [], []] => that's OK
In taskArray, the [] you are using is passed as a reference, and the elements in taskArray all reference the same array.
In taskArray2, you have three separate empty arrays, [], each with their own reference. Therefore you do not get duplicated values.
If you wish to create an array of empty arrays programmatically, use Array.from -
const fillEmptyArrays = (count) =>
Array.from(Array(count), _ => [])
const tasks =
fillEmptyArrays(3)
console.log(tasks)
// [ [], [], [] ]
And please don't include type names like Array in your variable names tasksArray; just name it tasks. JavaScript is a dynamically-typed language and this kind of thinking hurts you in the long run.
You need to get independent object references inside of the array, instead of having literally the constant value.
By taking Array.from with an object with a length property and the build in mapping function, you could get an array of independent arrays.
const tasksArray = Array.from({ length: 3 }, _ => [])
const tasks = ['task1', 'task2']
const fillWithData = (array) => {
tasks.forEach(task => {
array[0].push(task)
})
};
fillWithData(tasksArray);
console.log(tasksArray);
fill puts the value you pass it at each index of the array.
So tasksArray has three references to the same array, while tasksArray2 has a reference to each of three different arrays.
If you want to put three different arrays in there, then you need to explicitly create three arrays.
You could approach it with a counter:
const tasksArray2 = [];
let count = 3;
while (count--) {
tasksArray2.push([]);
}

Sort Javascript Object by Value [best practices?] [duplicate]

This question already has answers here:
Sort array of objects by string property value
(57 answers)
Closed 5 years ago.
Since there's no official way to sort an object by values, I'm guessing you either (1) Use an array instead or (2) Convert your object to an array using Object.entries(), sort it, then convert back to an object. But option (2) is technically unsafe since Javascript objects aren't supposed to have order.
Now I have a React app where I'm using Redux. I'm storing my data not as an array but as an object iterated by id values. This is what Redux suggests, and I would do it anyways, because of lookup times. I want to sort this redux data, so what I'm currently doing is option (2) of converting to array and then back to object. Which I don't really like.
My question is: Is this what everyone else does? Is it safe to sort an object?
Example:
const sortObject = (obj) => {
//return sorted object
}
var foo = {a: 234, b: 12, c: 130}
sortObject(foo) // {b: 12, c:130, a:234}
this is what I'm currently doing.
My object data structure looks something like this
obj = {
asjsd8jsadf: {
timestamp: 1234432832
},
nsduf8h3u29sjd: {
timestamp: 239084294
}
}
And this is how I'm sorting it
const sortObj = obj => {
const objArray = Object.entries(obj);
objArray.sort((a, b) => {
return a[1].timestamp < b[1].timestamp ? 1 : -1;
});
const objSorted = {};
objArray.forEach(key => {
objSorted[key[0]] = key[1];
});
return objSorted;
};
If you are using the Redux documentation for reference you should also have an array with all of the id's in it. Wouldn't it be easier to just sort that array and then use insertion sort when you add something to the state. Then you could use the sorted array to access the byId property of the state?

Categories

Resources