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();
});
Related
Firstly, I am trying to merge an array of many objects into a single array with every key in each object.
Lastly, any duplicate items in the array should be removed as well as any elements named "name".
Input:
const data = [
{
name: '10/20',
Tyler: 1,
Sonia: 0,
Pedro: 0,
},
{
name: '10/23',
Tyler: 0.5,
Sonia: 0.25,
Pedro: 0.75,
George: 0.5,
},
];
Output:
["Tyler", "Sonia", "Pedro", "George"]
This is what I've tried so far:
const mergedData = data.reduce((prev, cur) => {
const obj = cur[0];
const keys = Object.keys(obj);
const names = keys.splice(1);
return { names };
}, []);
I am trying to capture any key name other than "name" and add it to the final array. However, this is where I get stuck because I get this error, TypeError: Cannot convert undefined or null to object
Note: Objects may be different lengths, contain a mix of names, but never any duplicates.
An option is to find all keys put in a set and remove the name key
const data = [
{
name: '10/20',
Tyler: 1,
Sonia: 0,
Pedro: 0,
},
{
name: '10/23',
Tyler: 0.5,
Sonia: 0.25,
Pedro: 0.75,
George: 0.5,
},
];
const set = new Set(data.reduce((acc, i) => [...acc, ...Object.keys(i)], []));
set.delete('name');
const result = [...set];
console.log(result);
If you have access to ES6 methods, you can do this using a Set (unique values are ensured at creation) and converting it back into an array if you want through Destructuring.
data = [{name: '0', Tyler: '1', Dan: '2', Carl: '3'}, {name: '0', Tyler: '1', Dan: '2', Eric: '3', Danny: '4'}];
const output = (data) => {
let output = [];
// This makes sure you get each array and then strips just the keys as desired
data.forEach(item => {
output = output.
concat(Object.keys(item))
});
// This creates the set, strips our dups, and then spreads itself into an array
return [...new Set(output)]
// Strip out the 'name' key as needed
// NOTE: This should be a param instead of hard-coded, but this is easier to show
.filter(res => res != 'name');
}
console.log(output(data));
This should be fairly performant considering it only navigates the full array one time and each object itself shouldn't have millions of properties to cause .keys() any issues.
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])}`);
Say I have an object:
myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2', three: '3'} // (Edited) Added one more key here :)
};
I want a copy of this object without certain keys to a new object in a way that the output is as below:
newObj = {
name: 'Luke',
age: 12,
one: '1',
two: '2'
};
I have seen examples of destructing but I wanted to know if it is possible with nested objects. Is something like this doable using destructuring or if not what would be the most efficient way to do this.
One way to achieve this with destructure-like syntax would be like this:
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2', three : '3'}
};
const newObj = {
/* Copy over values from "myObj" to equivalent keys in "newObj" */
name : myObj.name,
age : myObj.age,
/* Spread keys "one" and "two" of the nested "others" object into "newObj" */
...({one, two} = myObj.others, {one, two})
}
console.log(newObj)
For completeness, an iife approach is possible. It works by creating an arrow function that takes as parameters keys you want to keep. In the function body, spread nested objects as desired.
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2'}
};
const newObj = (
({name, age, others}) => ({name, age, ...others})
)(myObj);
console.log(newObj);
For the object of unknown depth you can try using recursion.
Create a function which takes an object and array of keys to be removed as arguments.
Create a helper(which takes 1 object as parameter) function inside main and create empty object.
Loop through the properties of obj using for..in.
check if key is not present in the array of keys to be removed then
Check if the value is object then call the function recursively
If its not object then add it to the result obj.
At last return the result object.
The code will convert the object of unknown depth to a plain object and you can also remove keys from nested objects.
const myObj = {
name: 'Luke',
age: 12,
height: '163cm',
weight: '60kg',
others: { one: '1', two: '2'}
};
const removed = ['height','weight','one'];
function removeKeys(obj,removed){
const res = {};
function helper(obj){
for(let key in obj){
if(!removed.includes(key)){
if(typeof obj[key] === "object"){
helper(obj[key]);
}
else res[key] = obj[key]
}
}
}
helper(obj)
return res;
}
const res = removeKeys(myObj,removed);
console.log(res)
For an array I can do:
array.push(array.shift())
var array = [0, 1, 2, 3, 4, 5];
array.push(array.shift())
console.log(array); // [1, 2, 3, 4, 5, 0]
How can I do the same for an object?
Input
var object = {0: 'Fiat', 1: 'Audi', 2: 'BMW', 3: 'Citroën'}
How can I move {0: 'Fiat'} to the end of the object
Expected output:
{0: 'Audi', 1: 'BMW', 2: 'Citroën', 3: 'Fiat'}
You can use the following way
var object = {0: 'Fiat', 1: 'Audi', 2: 'BMW', 3: 'Citroën'};
var result = Object.keys(object).map(e => object[e]);
//console.log(result);
result.push(result.shift());
//console.log(result);
let ans = Object.assign({}, result);
console.log(ans);
You could convert you object with the given keys as index to an array, apply the shifting and convert back to an object.
var object = { 0: 'Fiat', 1: 'Audi', 4: 'BMW', 5: 'Citroën' },
array = Object.keys(object).reduce((r, k, i) => (r[i] = object[k], r), []);
array.push(array.shift());
console.log(Object.assign({}, array)); // { 0: "Audi", 1: "BMW", 2: "Citroën", 3: "Fiat" }
A different approach, while respecting the keys.
var object = { 0: 'Fiat', 1: 'Audi', 4: 'BMW', 5: 'Citroën' },
keys = Object.keys(object);
result = Object.assign(...keys.map((k, i) => ({ [k]: object[keys[(i + 1) % keys.length]] })));
console.log(result); // { 0: "Audi", 1: "BMW", 4: "Citroën", 5: "Fiat" }
The object's properties does not have any guarantee on the order, in which they may appear, concise there is no concept as order. I think you need to think more and can find another solution, which does not depend on the properties order.
You can convert your object into an array, do the reordering on the array and convert the array back to an object:
function toObject(arr) {
var rv = {};
for (var i = 0; i < arr.length; ++i)
rv[i] = arr[i];
return rv;
}
function toArray(object) {
return Object.keys(object).map(function (key) { return object[key]; });
}
var object = {0: 'Fiat', 1: 'Audi', 2: 'BMW', 3: 'Citroën'}
var array = toArray(object);
array.push(array.shift());
object = toObject(array);
console.log(object);
You should not rely on ordering of object's keys in JavaScript. It's not defined by standard. Objects by definition do not have an ordering, so there is no "end" of the object. It simply doesn't make sense to "move" a key of an object anywhere, since there's no ordering.
The data-structure which does have orders are arrays.
Your object is almost array-like, because all of its keys are consecutive numbers, but it's missing a lenght property. With length, you could turn it into an actual array with Array.from(object).
As Suren said, the object does not guarantee the insertion order. I suggest another approach for example:
const o = {0: 'Fiat', 1: 'Audi', 2: 'BMW', 3: 'Citroën'};
const k = Object.keys(o);
k.push(k.shift());
const result = k.map((v, i) => ({[i]: o[v]}))
.reduce((acum, v) => Object.assign(acum, v), {});
The approach here is to create and index array, apply the logic (push and shift) then re-build the object with map, and then merge them into one object with reduce. I think this could be shorter (just the reduce) but i wanted to split this up to be more clear.
Teaching: Objects are usually based on a Hash table for lookup by key.
As a consequence this usually means you do not have order.
myObj[key] => find value by computing hash of key => returns value
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);