Extract data from object based on key in JavaScript - javascript

I am trying to find the property value of an object based on key. I have below function getData which returns the data based on key passed as input parameter.
const getData = (key) => {
let row = {isSelected: true, Data: {Id: '1A', Value: 'LD'}};
return row[key];
}
console.log(getData('Data'));
In normal scenario it is working fine but how can I get the property value from nested object Data.Value.
If I call getData function as getData('Data.Value'), It should return LD.

You can use lodash's _.get() function that returns the value at a path:
const getData = path => {
const row = {isSelected: true, Data: {Id: '1A', Value: 'LD', InnerData: {Id: 1, Value: "Something"}}};
return _.get(row, path);
}
console.log(getData('Data'));
console.log(getData('Data.Value'));
console.log(getData('Data.InnerData.Value'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js" integrity="sha512-WFN04846sdKMIP5LKNphMaWzU7YpMyCU245etK3g/2ARYbPK9Ub18eG+ljU96qKRCWh+quCY7yefSmlkQw1ANQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

I would suggest accessing the nested value like this:
getData("Data").Value

This is what you want. It is not matter how deep is your row. Try this. It would be multilevel nested object too. For example
Data.InnerData.Value...
const getData = (key) =>{
let row = {isSelected: true, Data: {Id: '1A', Value: 'LD', InnerData: {Id: 1, Value: "Something"}}};
var keys = key.split('.');
var res = row;
for(var i=0; i < keys.length; i++){
res = res[keys[i]];
}
return res;
}
console.log(getData('Data.InnerData.Value'));

When you have dynamic object keys you can use javascript Object.keys method.
var data = getData("Data")
var dynamicKeys = Object.keys(data)
for(int i=0; i < dynamicKeys.length; i++){
console.log(data[dynamicKeys[i]])
}

If you are certain that your object goes two level at most, you can try this simple solution
const isObject = (value) => {
return typeof value === 'object' && !Array.isArray(value) && value !== null;
};
const testData = { isSelected: true, data: { id: '1A', value: 'LD' } };
const getData = (key) => {
const keys = key.split('.');
if (isObject(testData[keys[0]])) {
return testData[keys[0]][keys[1]];
}
return testData[keys[0]];
};
console.log(getData('data.id'));

Related

How to make object which store unique key have multiple different values

var data = [{type: 'physical', value: 'verified'},
{type: 'reference', value: 'owner'},
{type: 'physical', value: 'pending'},
{type: 'document', value: 'pending'}
]
How to return object in such a way which should have unique key which store mulpltiple values
Expected Result =
var data = {
physical: ['verified', 'pending'],
reference: ['owner'],
document: ['pending']
}
You can reduce the data array to an object and build the properties as well as the values in each property using spread operator, destructuring, and nullish coalescing.
data.reduce((acc, { type, value }) => ({
...acc,
[type]: [...(acc[type] ?? []), value]
}), {});
this function should return the result as you asked.
function getUnique(data){
let x = {};
for(let i of data){
if (!x[i.type]){x[i.type] = [];}
x[i.type].push(i.value);
}
return x;
}

How to dynamically add data from an array with objects to a nested array?

I have this set of data that I get dynamically -
This is the data I dynamically get
and my question is how can I get the values from the key, pattern and label and put them in a nested object like this - how should the nested object look like.
My current code is
let mergeTagsObj = {};
const merg = function(arr){
const propertyDataMap = arr.map(x => x.key);
propertyDataMap.forEach(x => {
mergeTagsObj[x] = {}
});
console.log(mergeTagsObj);
// console.log(object);
};
merg(displayArr)
displayArr has the data that I dynamically get, and I map each one to get the key so I can then give the object property a name. But after that I need to get the other 2 (pattern and label) and put it in the mergeTagsObj;
ex: mergeTagsObj = {
firstName:{
name:{label}
value:{pattern}
},
...
};
You can add the pattern and label in your forEach and any other logic that you might need to transform the data.
const data = [{key: 'firstName', pattern: "{{firstName}}", label: "First Name"},
{key: 'lastName', pattern: "{{lastName}}", label: "Last Name"},
{key: 'unsubscribeLink', pattern: "{{unsubscribeLink}}", label: "Unsubscribe Link"}
]
const transformDataToTagsObject = (dData) => {
const dynamicData = {};
dData.forEach((currentData, index) => {
const currentKey = currentData.key
const name = currentData.label
let value = currentData.pattern
if(currentData.key === 'unsubscribeLink'){
value = `<a href='${value}'>Unsubscribe</a>`
}
dynamicData[currentKey] = {
name,
value
}
})
const tagsObject = {
tags: dynamicData
}
return tagsObject;
}
const finalResults = transformDataToTagsObject(data)
console.log(finalResults)
Not most elegant solution, but I think this should work. Don't need to create the array of keys first you can just iterate over the arr of objects.
const merg = function(arr){
arr.forEach(x => {
mergeTagsObj[x.key] = {};
mergeTagsObj[x.key]['name'] = x.label;
mergeTagsObj[x.key]['value'] = x.pattern
});
console.log(mergeTagsObj);
// console.log(object);
};
// Given
const data = [
{key: "firstName", pattern: "{{firstName}}", label: "First Name"},
{key: "unsubscribeLink", pattern: "{{unsubscribeLink}}", label: "Unsubscribe Link"}
];
const tagsObject = data.reduce((obj, item) => {
const key = item.key;
const name = item.label;
let value = item.pattern;
if (key === 'unsubscribeLink') value = 'Unsubscribe';
return {...obj, [key]: {name, value}};
}, {});
console.log(tagsObject);

how to get array according to conditions in javascript

My array comes like this
var data=[{PRODUCT : P1}, {PRODUCT: P2}]
I wantt to convert this into [P1, P2].
Sometimes my array comes like this
var data=[{ITEM: I1, QUANTITY:1}, {ITEM: I2, QUANTITY:2}]
I wantt to convert this into [I1, I2].
so can we make a common function, where I just want to extract particular value of array and make a new array.
p.s. Thank you in advance
I tried to write the logic like this:
data.map((d, index) => { var result= [];
result.includes(d[0]); })
but it,s not dynamic
You could define a function which will always get the first value of the first object key, this should satisfy your needs based on the above
var data1 = [{
ITEM: 'I1',
QUANTITY: 1
}, {
ITEM: 'I2',
QUANTITY: 2
}]
var data2 = [{
PRODUCT: 'P1'
}, {
PRODUCT: ' P2'
}]
function getArrayOfValues(list) {
return list.reduce((acc, x) => {
const firstValue = Object.values(x)[0];
acc.push(firstValue)
return acc;
}, [])
}
const result1 = getArrayOfValues(data1)
console.log(result1)
const result2 = getArrayOfValues(data2)
console.log(result2)
function getProductOrItem(list) {
return list.reduce((accumulator, obj) => {
if (obj.PRODUCT) {
accumulator.push(obj.PRODUCT);
} else if (obj.ITEM) {
accumulator.push(obj.ITEM);
}
return accumulator;
}, [])
}
you can iterate through your array with map() method and inside it extract the value of a first entity of an object in your array and simply get a new array with all values:
const data1 =[{PRODUCT : 'P1'}, {PRODUCT: 'P2'}]
const data2 = [{ITEM: 'I1', QUANTITY: 1}, {ITEM: 'I2', QUANTITY: 2 }]
const transformValuesOfArray = (arrayToTransform) =>
arrayToTransform.map(value => {
const firstObjectValue = Object.values(value)[0]
return firstObjectValue
})
console.log(transformValuesOfArray(data1))
console.log(transformValuesOfArray(data2))

How to use spread operator to delete an object from array of objects using spread operator using react?

i want to delete an object from array of objects using spread operator.
i have an array of objects like below,
const list= [
{
id: '1',
name: 'first_item',
},
{
id: '2',
name: 'second_item',
},
]
i can add another object say "next_item" like below
const next_item = {
id: '3',
name: 'next',
}
const final = [...list, next_item]
similary how can i delete delete_item from list
const delete_item = {
id: '2',
name: 'second_item',
},
Could someone help me with this. thanks.
There is no such thing with spread operator, but if you still want to force, here you go
var arrayObj = [1,2,3,4,5,6]
const index = arrayObj.findIndex(elm => elm === 5)
const removed = [...arrayObj.slice(0,index) ,
...arrayObj.slice(index+1,arrayObj.length)]
console.log(removed)
But there is no benefit of using it like this
You can use some of the destructuring features like this :
var arrayObj = [1,2,3,4,5,6,7];
var [first , second , ...rest ] = arrayObj;
console.log(first , second , rest);
You can use filter
list = list.filter(item => {
return item.id !=2;
})
Or can use a function like the below
const removeFromList = (list, itemId) => {
return list.filter(item => {
return item.id != itemId;
});
}

How to concert [{ id:1, var1:val1, var2:val2, varX:[time1, time2, time3]}] into [{id:1, var1:val1, var2:val2, varX1:time1, varX2:time2, varX3:time3}]

I am working on a data format transformation which showed on the title, but I don't know how to figure out. I have tried to write the blow code to add the variable name for second dimensional array:
const data = [
{ id: 1, var1: 'val1', var2: 'val2', varX: ['time1', 'time2', 'time3'] },
{ id: 2, var1: 'val2', var2: 'val3', varX: ['time4', 'time5', 'time6'] },
];
const test = data.map((o) => o.varX);
for (i = 0; i < test.length; i++) {
const test2 = test[i].reduce((res, cur, idx) => {
res[`varX${idx}`] = cur;
return res;
}, {});
console.log(test2);
}
but what I expected result should be:
[{id:1, var1:val1, var2:val2, varX1:time1, varX2:time2, varX3:time3},{id:2, var1:val2, var2:val3, varX1:time4, varX2:time5, varX3:time6}]
Could anyone can guide me how to convert the data?
The issue with your code is that you're extracgint the properties that are not varX from the data by mapping only the values that have a varX. Then you do a good job at reducing them, but then you would have to merge the "left over" properties into the new object, it sounds a bit cumbersome to me. Instead, you could do something like the following:
const data = [
{ id: 1, var1: "val1", var2: "val2", varX: ["time1", "time2", "time3"] },
{ id: 2, var1: "val2", var2: "val3", varX: ["time4", "time5", "time6"] },
];
const test = data.map((o) => {
return Object.entries(o).reduce((p, [k, v]) => {
if (k === "varX") {
for (let index = 0; index < v.length; index++) {
p[`varX${index + 1}`] = v[index];
}
} else {
p[k] = v;
}
return p;
}, {});
});
console.log(test);
First, you map the data objects, then for each object you reduce their key/value pairs and check if the property is varX, if so, then you iterate through the array and assign to the new object the varX${index + 1} since you want the first property to be varX1, otherwise you just keep the same key/value pair.
You need create objects in reducemethod instead array, after replace varX to this new object by second map() method
const data = [{'id':1, 'var1':'val1', 'var2':'val2', 'varX':['time1', 'time2', 'time3']},
{'id':2, 'var1':'val2', 'var2':'val3', 'varX':['time4', 'time5', 'time6']}]
const test = data.map(item => item.varX);
const test2 = {}
for (i = 0; i < test.length; i++) {
test2[i] = test[i].reduce((accum, item, index) => {
return { ...accum, [`varX${index}`]: item};
}, {});
}
const dataX = data.map((item, index) => {
delete item.varX
return { ...item, ...test2[index] }
});
console.log(dataX)
Because of the first map in test, you are operating only on values of varX. You can just add another operation to merge the original data[i] objects with your new reduced varX objects.
const data = [
{ id: 1, var1: 'val1', var2: 'val2', varX: ['time1', 'time2', 'time3'] },
{ id: 2, var1: 'val2', var2: 'val3', varX: ['time4', 'time5', 'time6'] },
];
const test = data.map((o) => o.varX);
for (i = 0; i < test.length; i++) {
const test2 = test[i].reduce((res, cur, idx) => {
res[`varX${idx}`] = cur;
return res;
}, {});
// exclude varX and merge your new varX${i} back into data[i]
const {varX, ...test3} = Object.assign(data[i], test2);
console.log(test3);
}
Transform in-place code. I've deliberately avoided reduce, because the syntax becomes less readable and it adds performance overhead. The downside is that this code mutates the original data (transforms the data in-place). Can be easily mitigated by creating copies of objects val while mapping.
[1,2,3,4,5,6].forEach( i => eval(`time${i} = "time${i}";val${i} = "val${i}"`) );
const data = [{id:1, var1:val1, var2:val2, varX:[time1, time2, time3]}, {id:2, var1:val2, var2:val3, varX:[time4, time5, time6]}]
data.forEach((val, i)=>{
val.varX.forEach( (X,i) => val[`varX${i}`]=X );
delete val.varX;
console.log(val);
return val;
});
console.log(data);
I've created a version below using reduce and spread syntax. You can look at the spread syntax as simply an operation to copy properties to the new object being generated. I've used destructuring syntax to isolate varX from the rest of the properties and put them in varX and noVarX.
This also has the advantage of deep copying except for the final outside referenced objects in data.
[1,2,3,4,5,6].forEach( i => eval(`time${i} = "time${i}";val${i} = "val${i}"`) );
const data = [{id:1, var1:val1, var2:val2, varX:[time1, time2, time3]}, {id:2, var1:val2, var2:val3, varX:[time4, time5, time6]}]
const expanded = data.map(val => {
const {varX, ...noVarX} = val;
return {
...noVarX,
...varX.reduce( (res, cur, idx) =>
({ ...res, [`varX${idx}`]: cur }), {})
};
});
console.log(expanded);

Categories

Resources