I have a Javascript project in which I am trying to iterate through an Array that is found as a value inside a property, to get the key and from this key get its values from another object.
Right now I can only get the key of the property that contains only one value, I need to get the key of the properties that have arrays as value.
This is the input value:
let asset = "test";
This is the first object I need to get the key that the above value belongs to:
let testData = {
"data1": ["CAR,PLANE"],
"data2":["COUNTRY,CITY"],
"data3":"TEST"
};
This is the second object, from which I have to get the values depending on the previous key:
let dataObj = {
"data1": [
"t1Data1",
"t2Data1",
"t3Data1"
],
"data2": [
"t1Data2",
"t2Data2",
"t3Data2"
],
"data3": [
"t1Data3",
"t2Data3",
"t3Data3"
]
};
This is what I do to get the key:
let res = Object.keys(testData).find(key => testData[key] === asset.toUpperCase());
This is what it returns when the value is a single String:
data3
This is what it returns when the value is inside an array (let asset = "car";)
:
undefined
This is what I need:
data1
This is what I do to iterate through the array:
for(let getData of testData.data1) {
console.log(getData)
}
I need to iterate through the array when getting the key, but I don't know how to include this in the res variable.
CodePudding user response:
You can convert string values into array, while leaving array values unchanged and then use Array#includes
and Array#find
methods as follows:
const asset = "test",
dataObj = {
"data1": ["CAR","TRUCK","TRAIN"],
"data2": ["PLANT","TREE","SEEDLING"],
"data3": "TEST"
},
output = (o,k) => (Object.entries(o).find(
([key,value]) =>
[].concat(...[value]).includes(k.toUpperCase())
) ||
['NOT FOUND'])[0];
console.log( output(dataObj,asset) );
console.log( output(dataObj,"car") );
console.log( output(dataObj,"skooter") );
CodePudding user response:
Maybe you could try something like this ?
let res = Object.keys(testData).find(key => typeof testData[key] === 'object' ? testData[key].includes(asset.toUpperCase()) : testData[key] === asset.toUpperCase());
CodePudding user response:
You need to go through each item in the array:
let dataObj = {
data1: ['t1Data1', 't2Data1', 't3Data1'],
data2: ['t1Data2', 't2Data2', 't3Data2'],
data3: ['t1Data3', 't2Data3', 't3Data3'],
};
let testData = {
data1: ['CAR,PLANE'],
data2: ['COUNTRY,CITY'],
data3: 'TEST',
};
let asset = 'car';
let res = Object.keys(testData).find(key => {
const value = testData[key]
if (Array.isArray(value)) {
// Go through each item in the array and compare
return value.some(item => item.toLowerCase().includes(asset))
}
return value.toLowerCase().includes(asset)
})
console.log(res);
CodePudding user response:
The value of data1
is ["CAR,PLANE"]
. A single element in an array. Your logic assumes "CAR" and "PLANE" are 2 individual string elements of an array. You can change your code to the following (assuming you always have a single element in the array).
let dataObj = {
data1: ['t1Data1', 't2Data1', 't3Data1'],
data2: ['t1Data2', 't2Data2', 't3Data2'],
data3: ['t1Data3', 't2Data3', 't3Data3'],
};
let testData = {
data1: ['CAR,PLANE'],
data2: ['COUNTRY,CITY'],
data3: 'TEST',
};
let asset = 'car';
let res = Object.keys(testData).find((key) =>
typeof testData[key] === 'object'
? testData[key][0].includes(asset.toUpperCase())
: testData[key] === asset.toUpperCase()
);
console.log(res);
Notice the [0]
in ? testData[key][0].includes(asset.toUpperCase())
.
If your example is wrong and ["CAR,PLANE"]
should really be ["CAR", "PLANE"]
, I believe your code should work.
CodePudding user response:
Presented below is one possible way to achieve the desired objective.
Code Snippet
// method to find the key
const findKeyFor = (val, obj) => (
// iterate over key-value pairs of given object 'obj'
Object.entries(obj)
// find key-value pair where
// value matches the "asset"
.find(([k, v]) => [v].flat().some(
// [v].flat() accounts for value in "testData"
// being either string or array of string
elt => elt.split(',').some(
// "elt.split()" accounts for string separated
// by comma such as "CAR,PLANE"
w => w === val.toUpperCase()
)
))
?.[0] // extract only the "key"
?? 'not found' // if not found,
);
const testData = {
"data1": ["CAR,PLANE"],
"data2":["COUNTRY,CITY"],
"data3":"TEST"
};
let asset1 = 'test';
let asset2 = 'car';
console.log(
'find key for "test": ',
findKeyFor(asset1, testData)
);
console.log(
'find key for "car": ',
findKeyFor(asset2, testData)
);
let dataObj = {
"data1": [
"t1Data1",
"t2Data1",
"t3Data1"
],
"data2": [
"t1Data2",
"t2Data2",
"t3Data2"
],
"data3": [
"t1Data3",
"t2Data3",
"t3Data3"
]
};
// to get the value from "dataObj" using the above method
console.log(
'get dataObj array for "test": ',
dataObj?.[findKeyFor('test', testData)]
);
console.log(
'get dataObj array for "car": ',
dataObj?.[findKeyFor('car', testData)]
);
.as-console-wrapper { max-height: 100% !important; top: 0 }
Explanation
Inline comments added to the snippet above.