I am trying to access an object within an object using the key from another object.
I have two objects:
const OutputReference = {Key1: "Some Random String",Key2: "Some Random String"}
const masterKey = {
...
'Key1':{
Label: "Key 1",
view: [1,2,3],
},
'Key2':{
Label: "Key 2",
view: [4,5,6],
},
...
}
OutputReference contains multiple keys and values, and I want match these keys to the keys in masterKey to grab each corresponding 'view'. So far, I use this function to break out OutputReference into a key (k) and value (v):
Object.keys(OutpufReference).filter(([k,v])=>{
...
//code here
...
});
I then want to grab "view" for the corresponding key and store it in an array. I used:
var tempArr = []
tempArr.push(masterKey.k.view)
Making the entire function:
Object.keys(OutpufReference).filter(([k,v])=>{
...
var tempArr = []
tempArr.push(masterKey.k.view)
...
});
The issue is masterKey.k is coming back undefined. Note console.log(k) in this case outputs exactly this: Key1
What I have tried (just to access k):
tempArr.push(masterKey.k)
tempArr.push(masterKey[k])
var temp = JSON.stringify(k)
tempArr.push(masterKey[temp])
Object.keys(masterKey).forEach((v,i)=>{
if(v === k) //k is the index from mapping OutputReference
tempArr.push(masterKey.v)
})
None of these work; all return an undefined object (masterKey.v, masterKey[temp], etc.). Note, when doing console.log() on each of these keys (temp, v, k), it outputs the string Key1. However, using
tempArr.push(masterKey.Key1)
Places the correct value in tempArr (Being the object Key1). This is not ideal however, as there are many keys and values in masterKey and OutputReference only contains a few of them.
Where I looked
I researched mozilla's guide on objects, which led me to my previous attempts Mozilla. I also researched this thread Deleting a property from a javascript object.
However it recommends what I have already tried.
I see from this thread that JavaScript objects can only use strings as keys, so why doesn't stringifying my key in
var temp = JSON.stringify(k)
tempArr.push(masterKey[temp])
work?
The final output desired: The array tempArr containing every view that outputReference matched with masterKey (In this case: tempArr = [[1,2,3],[4,5,6])
If I understood correctly, your end goal is to insert in each position of the array tempArr the value of the property "view" nested inside of the first level properties of the masterKey object. But you only want to push to the tempArr keys that are contained inside of the OutputReference object.
The code below will push the arrays inside of each view property nested in the properties Key1 and Key2 into tempArray.
const OutputReference = {
Key1: "Some Random String",
Key2: "Some Random String"
}
const masterKey = {
'Key1': {
Label: "Key 1",
view: [1, 2, 3],
},
'Key2': {
Label: "Key 2",
view: [4, 5, 6],
}
}
const tempArr = []
for (keys in OutputReference) {
if (Object.hasOwn(masterKey, keys)) {
tempArr.push(masterKey[keys]["view"])
console.log('The following content is being pushed to the array: ', masterKey[keys]["view"])
}
}
console.log('This is the content of tempArray:', tempArr)
Alternatively you can use
const OutputReference = {
Key1: "Some Random String",
Key2: "Some Random String"
}
const masterKey = {
'Key1': {
Label: "Key 1",
view: [1, 2, 3],
},
'Key2': {
Label: "Key 2",
view: [4, 5, 6],
}
}
const tempArr = []
Object.keys(OutputReference).forEach((key, value) => {
if (Object.hasOwn(masterKey, key)) {
tempArr.push(masterKey[key]["view"])
}
console.log('The following content is being pushed to the array: ', masterKey[key]["view"])
})
console.log('This is the content of tempArray:', tempArr)
I hope this works for you
You were close, but instead of filter, use map on the object keys to create the array
tempArr = Object.keys(OutputReference).map(m => masterKey[m].view)
const OutputReference = {
Key1: "Some Random String",
Key2: "Some Random String"
}
const masterKey = {
'Key1': {
Label: "Key 1",
view: [1, 2, 3],
},
'Key2': {
Label: "Key 2",
view: [4, 5, 6],
},
'Key3': {
Label: "Key 3",
view: [4, 5, 6],
},
}
const tempArr = Object.keys(OutputReference).map(m => masterKey[m].view)
console.log(tempArr)
Related
I have an Object
let data = {
a: 1,
b: 2,
c: {
abc: "ak",
bcd: "gh",
cfv: "ht"
}
}
then I have variables which I need to show with these object value
let abc = "first 1", bcd="sec2", cfv="third3" , def="fourth 4", tdf = "fifth 5";
Now the Object will come in API call it can be any of these variable.
How can I match the variable name with the object data.c.(object key) and concatinate their value.
for example the output should be
As we have (abc, bcd, cfv) as our object key then the output would be
first 1ak ==> that is the value of (abc + data.c["abc"])
sec2gh ==> that is the value of (bcd + data.c["bcd"])
third3ht ==> that is the value of (cfv + data.c["cfv"])
I tried using Object.keys() method so from this method we will get the object keys in array then how can I match with the variable name -
Object.keys(data.c);
==> ["abc", "bcd", "cfv"] (After this how can I proceed to match the variable and show their values?)
Shall I loop throught the object that (data.c)?
Please help me giving some ideas to achieve this implementation.
thank you
If it's possible for you to amend the format of your abc, bcd etc. variables to be the properties in an object, then this problem becomes trivial. You can use flatMap() to create a new array of the output values by linking the properties of the two target objects, like this:
let values = {
abc: "first 1",
bcd: "sec2",
cfv: "third3",
def: "fourth 4",
tdf: "fifth 5"
}
let data = {
a: 1,
b: 2,
c: {
abc: "ak",
bcd: "gh",
cfv: "ht"
}
}
let output = Object.keys(values).flatMap(k => data.c.hasOwnProperty(k) ? values[k] + data.c[k] : []);
console.log(output);
Is there any operation in Javascript just like [x for x in array] in python?
For example, I'm using javascript to reading a json file where there're dozens of (key, value) pairs needed to be handled(or transformed into other format). And I thought working in this way is stupid:
let transformed = []
for (let key in json){
transformed = [ /* doing some transform*/ ]
}
Is there anything like:
let transformed = [
lambda function1(key), lambda function2(value) for key, value in json
]
Thanks in advance.
The rough equivalent of Python's list comprehension is Array.map:
const myArray = [1, 2, 3]
const transformed = myArray.map((item) => item + 1)
// [2, 3, 4]
But your example is not about an array, but about an Object with keys and values. In Python, this would be a dict, and you'd use a dict comprehension along the lines of {function1(key): function2(value) for key, value in my_dict.items()}.
In JavaScript, you can turn such an object into an array with Object.entries, then perform the map, and finally transform it back into an object using Object.fromEntries:
const myObject = { a: 1, b: 2 }
const transformed = Object.fromEntries(Object.entries(myObject)
.map(([key, value]) => [key + 'x', value + 1]))
// { ax: 2, bx: 3 }
Note that fromEntries is fairly new and you might need to add a polyfill for it.
You can use a code likes this. You must use a function that handle operation on current single item.
const words = ['hello', 'bird', 'table', 'football', 'pipe', 'code'];
const capWords = words.forEach(capitalize);
function capitalize(word, index, arr) {
arr[index] = word[0].toUpperCase() + word.substring(1);
}
console.log(words);
// Expected output:
// ["Hello", "Bird", "Table", "Football", "Pipe", "Code"]
First of all, javascript does NOT support Associative Arrays. If you are used to them in Python, PHP, and other languages you need to do a little workaround in JS to achieve the same functionality.
The most common way to simulate an associative array is using an object.
let testObject = {name: "Color", value: "Red"};
And then you push every object into an array so you end up with something like this:
let testArray = [{name: "Color", value: "Red"}, {name: "Color", value: "Blue"}];
Once you have this array consisting of objects, you can use map function to go through every object in the array and do whatever you want with it.
testArray.map((item, index) => {
console.log("The value of "+index+". item is: "item.value);
})
You can use Array.map() function. It work pretty like Array.forEach() function
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map((element) => {
return element * 2
})
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
It can be reduce using
const numbers = [1, 2, 3, 4, 5]
let newArray = numbers.map(element => element * 2)
console.log(newArray) // excepted : [ 2, 4, 6, 8, 10 ]
For more informations, you can this documentation https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Global_Objects/Array/map
I've got two arrays that have multiple objects
[
{
"name":"paul",
"employee_id":"8"
}
]
[
{
"years_at_school": 6,
"department":"Mathematics",
"e_id":"8"
}
]
How can I achieve the following with either ES6 or Lodash?
[
{
"name":"paul",
"employee_id":"8"
"data": {
"years_at_school": 6
"department":"Mathematics",
"e_id":"8"
}
}
]
I can merge but I'm not sure how to create a new child object and merge that in.
Code I've tried:
school_data = _.map(array1, function(obj) {
return _.merge(obj, _.find(array2, {employee_id: obj.e_id}))
})
This merges to a top level array like so (which is not what I want):
{
"name":"paul",
"employee_id":"8"
"years_at_school": 6
"department":"Mathematics",
"e_id":"8"
}
The connector between these two is "employee_id" and "e_id".
It's imperative that it's taken into account that they could be 1000 objects in each array, and that the only way to match these objects up is by "employee_id" and "e_id".
In order to match up employee_id and e_id you should iterate through the first array and create an object keyed to employee_id. Then you can iterate though the second array and add the data to the particular id in question. Here's an example with an extra item added to each array:
let arr1 = [
{
"name":"mark",
"employee_id":"6"
},
{
"name":"paul",
"employee_id":"8"
}
]
let arr2 = [
{
"years_at_school": 6,
"department":"Mathematics",
"e_id":"8"
},
{
"years_at_school": 12,
"department":"Arr",
"e_id":"6"
}
]
// empObj will be keyed to item.employee_id
let empObj = arr1.reduce((obj, item) => {
obj[item.employee_id] = item
return obj
}, {})
// now lookup up id and add data for each object in arr2
arr2.forEach(item=>
empObj[item.e_id].data = item
)
// The values of the object will be an array of your data
let merged = Object.values(empObj)
console.log(merged)
If you perform two nested O(n) loops (map+find), you'll end up with O(n^2) performance. A typical alternative is to create intermediate indexed structures so the whole thing is O(n). A functional approach with lodash:
const _ = require('lodash');
const dataByEmployeeId = _(array2).keyBy('e_id');
const result = array1.map(o => ({...o, data: dataByEmployeeId.get(o.employee_id)}));
Hope this help you:
var mainData = [{
name: "paul",
employee_id: "8"
}];
var secondaryData = [{
years_at_school: 6,
department: "Mathematics",
e_id: "8"
}];
var finalData = mainData.map(function(person, index) {
person.data = secondaryData[index];
return person;
});
Sorry, I've also fixed a missing coma in the second object and changed some other stuff.
With latest Ecmascript versions:
const mainData = [{
name: "paul",
employee_id: "8"
}];
const secondaryData = [{
years_at_school: 6,
department: "Mathematics",
e_id: "8"
}];
// Be careful with spread operator over objects.. it lacks of browser support yet! ..but works fine on latest Chrome version for example (69.0)
const finalData = mainData.map((person, index) => ({ ...person, data: secondaryData[index] }));
Your question suggests that both arrays will always have the same size. It also suggests that you want to put the contents of array2 within the field data of the elements with the same index in array1. If those assumptions are correct, then:
// Array that will receive the extra data
const teachers = [
{ name: "Paul", employee_id: 8 },
{ name: "Mariah", employee_id: 10 }
];
// Array with the additional data
const extraData = [
{ years_at_school: 6, department: "Mathematics", e_id: 8 },
{ years_at_school: 8, department: "Biology", e_id: 10 },
];
// Array.map will iterate through all indices, and gives both the
const merged = teachers.map((teacher, index) => Object.assign({ data: extraData[index] }, teacher));
However, if you want the data to be added to the employee with an "id" matching in both arrays, you need to do the following:
// Create a function to obtain the employee from an ID
const findEmployee = id => extraData.filter(entry => entry.e_id == id);
merged = teachers.map(teacher => {
const employeeData = findEmployee(teacher.employee_id);
if (employeeData.length === 0) {
// Employee not found
throw new Error("Data inconsistency");
}
if (employeeData.length > 1) {
// More than one employee found
throw new Error("Data inconsistency");
}
return Object.assign({ data: employeeData[0] }, teacher);
});
A slightly different approach just using vanilla js map with a loop to match the employee ids and add the data from the second array to the matching object from the first array. My guess is that the answer from #MarkMeyer is probably faster.
const arr1 = [{ "name": "paul", "employee_id": "8" }];
const arr2 = [{ "years_at_school": 6, "department": "Mathematics", "e_id": "8" }];
const results = arr1.map((obj1) => {
for (const obj2 of arr2) {
if (obj2.e_id === obj1.employee_id) {
obj1.data = obj2;
break;
}
}
return obj1;
});
console.log(results);
I need to get a list of all the key names in the following JSON object:
var myJSON = [
{
"Employees_Name": "Bill Sanders",
"Work_plan_during_my_absence": "Work from home",
"Assigned To-Manager Approval": [
"mymanager#gmail.com"
],
"AbsenceVacation_Summary": [
{
"Computed_Leave_Days": 2,
"From_Date": "2018-08-20",
"To_Date": "2018-08-21",
"Id": "Shccbcc230_a30f_11e8_9afa_25436d674c51"
}
],
"Leave_Type": "Work from Home",
"Reporting_Manager": "My Manager",
"Total_Days": 2,
}
]
When I use the Object.keys method, it retrieves only the top level key names:
var keys_arr = Object.keys(myJSON[0]);
console.log(keys_arr);
The result is an array:
"[ 'Employees_Name', 'Work_plan_during_my_absence', 'Assigned To-Manager
Approval', 'AbsenceVacation_Summary', 'Leave_Type', 'Reporting_Manager',
'Total_Days']"
The key names that are missing are the ones inside of 'AbsenceVacation_Summary'.
I think what I need to do is loop through the array of names returned and see if the value is an object or an array...but I don't know how to do this. Please advise.
You're right you need to walk your object structure recursively to discover nested objects and collects their keys:
function collectKeys(inputObject, outputKeys) {
if (Array.isArray(inputObject)) {
for(let i = 0; i < inputObject.length; i++) {
collectKeys(inputObject[i], outputKeys);
}
} else if (typeof inputObject === 'object') {
Object.keys(inputObject).forEach(function(key) {
outputKeys.push(key);
collectKeys(outputKeys[key], outputKeys);
});
}
}
var collectedKeys = [];
collectKeys(myJSON, collectedKeys);
Working fiddle here
Result will show in console
References
javascript typeof
javascript Array.isArray
javascript Array.forEach
I am trying to pass a function that removes duplicates from an array. It should handle strings, object, integers as well. In my code so far I am showing that it will handle strings but nothing else. How can Imake this function universalto handle numbers,handle arrays,handle objects, and mixed types?
let unique = (a) => a.filter((el, i ,self) => self.indexOf(el) ===i);
In this function I hav unique() filtering to make a new array which checks the element and index in the array to check if duplicate. Any help would be appreciated.
i think the first you should do is to sort the array ( input to the function ). Sorting it makes all the array element to be ordered properly. for example if you have in an array [ 1, 3, 4, 'a', 'c', 'a'], sorting this will result to [ 1 , 3 , 4, 'a', 'a' , 'c' ], the next thing is to filter the returned array.
const unique = a => {
if ( ! Array.isArray(a) )
throw new Error(`${a} is not an array`);
let val = a.sort().filter( (value, idx, array) =>
array[++idx] != value
)
return val;
}
let array = [ 1 , 5, 3, 2, "d", "q", "b" , "d" ];
unique(array); // [1, 2, 3, 5, "b", "d", "q"]
let obj = { foo: "bar" };
let arraySize = array.length;
array[arraySize] = obj;
array[arraySize++] = "foo";
array[arraySize++] = "baz";
array[arraySize++] = obj;
unique(array); // [1, 2, 3, 5, {…}, "b", "baz", "d", "foo", "hi", "q"]
it also works for all types, but if you pass in an array literal with arrays or objects as one of its element this code will fail
unique( [ "a", 1 , 3 , "a", 3 , 3, { foo: "baz" }, { foo: "baz" } ] ); // it will not remove the duplicate of { foo: "baz" } , because they both have a different memory address
and you should also note that this code does not return the array in the same order it was passed in , this is as a result of the sort array method
Try using sets without generics. You can write a function as
Set returnUnique(Object array[]) {
Set set=new HashSet();
for (Object obj:array) {
set.add(obj);
}
return set;
}