Object.entries() removing the main key name - javascript

I want to parse this dictionary:
var data = {'Charlie':
{'keys':
{'a': '1',
'b':['1', '2', '3'],
'c': '3'},
},
'Derek':
{'keys':
{'a': '10',
'b': ['9', '8', '7'],
'c': '9'},
}
};
But I want "Charlie" and "Derek" to appear as li names instead of Dummy. Still - I can't since I don't see them in response. They disappear after parsing, leaving:
'keys':
{'a': '1',
'b':['1', '2', '3'],
'c': '3'}
and
'keys':
{'a': '10',
'b': ['9', '8', '7'],
'c': '9'},
The full code:
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js"></script>
</head>
<body>
<div>
<h3>Div underneath</h3>
<ul id="main-ul">
</ul>
</div>
</body>
<script>
var data = {'Charlie':
{'keys':
{'a': '1',
'b':['1', '2', '3'],
'c': '3'},
},
'Derek':
{'keys':
{'a': '10',
'b': ['9', '8', '7'],
'c': '9'},
}
};
lay_out_tab_structure(data)
function lay_out_tab_structure(response) {
console.log("response in lay_out_tab is", response)
var ul = $('#main-ul');
for (const [key, value] of Object.entries(response)) {
var li = document.createElement('li')
var div = document.createElement('div')
li.append(div);
ul.append(li);
console.log("The key-value pair before passing is", (key, value))
create_row(li, (key, value))
}
};
function create_row(listItem, content) {
console.log("Content in create row is", content)
var mainDiv = $(listItem).children('div');
var name = $('<p class="css-big-letter machine-name">'+'<a style="color:inherit;">'+"Dummy"+'</a>'+'</p>');
var titleDiv = $('<div style="position:relative;margin-bottom:1%;"></div>');
titleDiv.append(name);
mainDiv.append(titleDiv);
var RowDiv = $('<div></div>');
$(mainDiv).append(RowDiv);
};
</script>
</html>
Can you help me?
I have already tried this solution and I couldn't get it working:
Object.entries() turning keys into arrays

Object.entries() will, as your code reflects, provide you with a list of 2-element arrays. Your code destructures each of those arrays into your key and value variables. All of that is fine.
However, when you want to pass both the key and the value to another function, you'll have to either pass each as a separate parameter, or else collect them back into a 2-element array. The statement
create_row(li, (key, value))
does not do either of those things. The expression (key, value) is a comma expression and will evaluate only to value, as you've found out. Thus, you could either change create_row() to accept a total of 3 parameters and pass key and value individually, or else group those two into a new array:
create_row(li, [key, value])
Either way will work. If you go with the array, then inside create_row() the key will be content[0] and the value will be content[1].

Related

Convert 2D JS array to json string

My array in variable is:
"1": ["48": '1', "49": '2']
"2": ["51": '3', "52": '4', "53": '5', "54": '6']
"3": ["30": '7']
I've mentioned key and value here for the 2D array, I'm trying to convert this to JSON string. I tried JSON.stringify(arraydata), arraydata is the variable where the array is stored, but it makes the string empty, whereas array data is correct.
Edit:
This is how I'm adding array data:
var arraydata = new Array();
$('.classselector').each(function(){
let key1= $(this).data('key1');
let key2= $(this).data('key2');
if ( !Array.isArray(arraydata['"'+key1+'"']) ) {
arraydata['"'+key1+'"'] = new Array();
}
arraydata['"'+key1+'"']['"'+key2+'"'] = $(this).val();
});
The "array" quoted in your question is not valid JavaScript code. Maybe you had on object of objects instead? In that case the object can easily be converted into a JSON string:
const obj={"1": {"48": '1', "49": '2'},
"2": {"51": '3', "52": '4', "53": '5', "54": '6'},
"3": {"30": '7'}};
console.log(JSON.stringify(obj));
// in case you were really talking about
// a sparsely populated array of arrays,
// then the solution could look like this:
const arr=[];
arr[1]=[];
arr[1][48]='1';
arr[1][49]='2';
arr[2]=[];
arr[2][51]='3';
arr[2][52]='4';
arr[2][53]='5';
arr[2][54]='6';
arr[3]=[];
arr[3][30]='7';
console.log(arr);
console.log(JSON.stringify(arr));
See my comment above. Use objects instead of arrays!
Your corrected script could look something like this:
var arraydata = {};
$('.classselector').each(function(){
let key1= $(this).data('key1');
let key2= $(this).data('key2');
if ( !arraydata[key1] ) {
arraydata[key1] = {};
}
arraydata[key1][key2] = $(this).val();
});

Best way to access key, value pair inside of an array of objects? in javascript

I'll try my best to explaing as throughly as possible but first I'll just paste what I have so far:
var test = 'select imei, phone_number from userinfo';
const result = await pgClient.query(test);
const resultString = result.rows;
var a = [];
for(let i = 0; i < resultString.length; i +=1){
let obj = resultString[i];
//let data = [obj];
// res = data.reduce((acc, curr) => {
// acc[curr.imei] = curr.phone_number;
// return acc;
// }, {} );
a.push(obj)
}
console.log(a)
so basically after querying that select statment, I get an obj like this {imei, number} and then push that to an array so it more looks like this
var jsObjects = [
{imei: '11', number: '+11'},
{imei: '12', number: '+12'},
{imei: '13', number: '+13'},
{imei: '14', number: '+14'}
];
But if you uncomment the code above and replace a.push(obj) with a.push(res) it can also look like this
[
{ '11': '+11' },
{ '12': '+12'},
]
So the MAIN reason for all of this is becasue im trying to create a function so that
if (a.imei('11')) {
return a.phonenumber('+11')
}
Return the phone number associated with the given imei number.
And the actual question is which format is best to access key, value pair? and how would i access the actual value based on the key? Sorry for being all over, I really dont know how else to explain and ask this. Thank you
I think I understand that you'd like a fast lookup of a number value given an "imei" value. The loop as written in the OP doesn't do anything to the result string except move the same values into a new array called a, so either with a or resultString, do this...
const jsObjects = [
{imei: '11', number: '+11'},
{imei: '12', number: '+12'},
{imei: '13', number: '+13'},
{imei: '14', number: '+14'}
];
const imeiIndex = jsObjects.reduce((acc, obj) => {
acc[obj.imei] = obj.number;
return acc;
}, {});
console.log(imeiIndex)
With that, given an "imei" value later, the associated number can be looked up fast with...
let someImeiValue = '14';
let quicklyLookedupNumber = imeiIndex[someImeiValue]; // <- this will be '+14'
Also, note...
It's often a good idea to keep the whole object being indexed in the way just described, like this:
const jsObjects = [
{imei: '11', number: '+11', someOtherProp: 1 },
{imei: '12', number: '+12', someOtherProp: 2 },
{imei: '13', number: '+13', someOtherProp: 3 },
{imei: '14', number: '+14', someOtherProp: 4 }
];
const imeiIndex = jsObjects.reduce((acc, obj) => {
acc[obj.imei] = obj; // <-- NEW: store the whole object in the index
return acc;
}, {});
// now indexed data contains as much info as the original array
console.log(imeiIndex);
let key = '12';
console.log(`the object at key ${key} is ${JSON.stringify(imeiIndex[key])}`);

In Javascript remove keys from object not in an Array

Suppose I have a list of objects with many keys and I want to keep only certain keys from them.
This is how I am doing it.
The Problem with other good solutions on SO are that if a key is not present in the keys to keep it still adds a key, value where the value is undefined.
let data = [{
'a': 1,
'b': 2,
'c': 3
},
{
'a': 1,
'c': 3,
'd': 4
}]
const keys_to_keep = ['a', 'b']
data = data.map((obj) => {
Object.keys(obj).forEach(function(key) {
if(!keys_to_keep.includes(key))
delete obj[key]
});
return obj;
})
Output :
[ { a: 1, b: 2 }, { a: 1} ]
Is there a better way to get this done.
Any help is appreciated.
A couple of improvements.
You're using .map() which creates a new array, but then you're just assigning it to the old variable. So, you apparently don't need to create a new array at all, you can just iterate the one you have and modify it.
Put the properties you want to keep in a Set instead of an Array for potentially faster lookup.
for/of loops are generally favored over .forEach() loops because of better flow control options (break, continue, return, etc...) and more opportunities for compiler optimization.
let kv = [{
'a': 1,
'b': 2,
'c': 3
},
{
'a': 1,
'b': 2,
'c': 3,
'd': 4
}]
const l = new Set(['a', 'b']);
for (let obj of kv) {
for (let prop of Object.keys(obj)) {
if (!l.has(prop)) {
delete obj[prop];
}
}
}
console.log(kv);
You can use Object.fromEntries, after map and filter to keep only the relevant keys:
let data = [{'a': 1,'b': 2,'c': 3},{'a': 1,'c': 3,'d': 4}]
const keys_to_keep = ['a', 'b']
var result = data.map(obj =>
Object.fromEntries(keys_to_keep.map(key =>
obj.hasOwnProperty(key) && [key, obj[key]]
).filter(Boolean))
);
console.log(result);

Extending objects in array without redefining

I've got an array of objects
var myArray = [{'id':'1','value':'firstValue'},{'id':'1','value':'secondValue'}, etc.]
I want to be able to extend the array later on in the code, so that I will have
var myArray = [{'id':'1','value':'firstValue', 'anothervalue':'anotherFirstValue'},{'id':'1','value':'secondValue', 'anothervalue':'anotherSecondValue'}, etc.]
Is there a way to do it without redefining myArray?
You can map the array, and add to each object:
var myArray = [{
'id': '1',
'value': 'firstValue'
}, {
'id': '1',
'value': 'secondValue'
}];
//later on
myArray = myArray.map(function(obj) {
obj.anothervalue = 'anotherFirstValue';
return obj;
});
console.log(myArray);

ES6 specific method to loop through two arrays and find matches in each?

Let's say I have two arrays of objects that I want to compare:
var arr1 = [
{
name: 'A', type: "Dog"
},
{
name: 'B', type: "Zebra"
},
{
name: 'C', type: "Cat"
},
{
name: 'D', type: "Dingo"
}
]
var arr2 = [
{
name: 'A', type: "Wolf"
},
{
name: 'B', type: "Echidna"
},
{
name: 'C', type: "Wallaby"
},
{
name: 'D', type: "Rabbit"
}
]
Pretend that arr1 is old data, and arr2 is updated data coming from an API.
I want to loop through the arrays, finding objects whose name matches. If there is a match, I want to update the type from arr1 to arr2.
I'd do this like so:
for(var i = 0; i<arr1.length; i++){
for(var x = 0; x<arr2.length; x++){
if(arr1[i].name === arr2[x].name){
arr1[i].type = arr2[x].type;
}
}
}
I'm wondering if there are any updated ways in ECMAScript 6 which make this easier to do (in a real world scenario the logic is a lot more complex and looping within a loop feels rather clunky);
In ES2015 you wouldn't use this data structure, you would use maps:
var map1 = new Map([
['A', "Dog"],
['B', "Zebra"],
['C', "Cat"],
['D', "Dingo"]
]);
var map2 = new Map([
['A', "Wolf"],
['B', "Echidna"],
['C', "Wallaby"],
['D', "Rabbit"]
]);
And then, to update map1 with the data from map2, you would use
for(let [key, value] of map2)
map1.set(key, value);
Map operations are required to be sublinear on average. They should be constant if the map is implemented with a hash. Then the total cost would be linear.
Alternatively, since the keys are strings, you can consider using a plain object. You can create it with Object.create(null) to prevent it from inheriting properties from Object.prototype, and assign the properties with Object.assign
var obj1 = Object.assign(Object.create(null), {
A: "Dog",
B: "Zebra",
C: "Cat",
D: "Dingo"
});
var obj2 = Object.assign(Object.create(null), {
A: "Wolf",
B: "Echidna",
C: "Wallaby",
D: "Rabbit"
});
And then, to update obj1 with the data from obj2, you would use
for(let key in obj2)
obj1[key] = obj2[key];
Most probably the object will be implemented using a hash, so each assignment will be constant on average. The total cost would be linear.
You can use a forEach loop (ES5) or the for..of loop from ES6:
for (let item1 of arr1) {
for (let item2 of arr2) {
if(item1.name === item2.name){
item1.type = item2.type;
}
}
}
If these lists are quite long I would suggest putting the updated list into a hash map so your time complexity is linear rather than quadratic.

Categories