Using reduce() changes order of array [duplicate] - javascript

This question already has answers here:
Does JavaScript guarantee object property order?
(13 answers)
Closed 4 years ago.
Within the example script I have generated two arrays I would like to combine to a single row:
var testHeaders = ["aLabel", "bLabel", "cLabel","dLabel","eLabel"];
and
var testValue = ["aValue","bValue", "cValue","dValue","eValue"];
What I am trying to achieve is a string like { aLabel = aValue, bLabel = bValue, ... } that can be used to upload into BigQuery (the data upload job works).
I found a piece of code that almost does this, but somehow it changes the order of the elements within the two arrays.
var code = testValue.reduce(function(obj, value, index) {
obj[testHeaders[index]] = value;
return obj
}, {})
However, the result does mix up the order of the arrays as seen below. I am not capable of figuring out why the order changes. As far as I know, reduce() should work its way from left to right in an array.
The returned object is:
{
aLabel = aValue,
dLabel = dValue,
bLabel = bValue,
eLabel = eValue,
cLabel = cValue
}

You can use map and join:
var testHeaders = ["aLabel", "bLabel", "cLabel","dLabel","eLabel"];
var testValue = ["aValue","bValue", "cValue","dValue","eValue"];
var res = '{' + testHeaders.map((label, i) => `${label}=${testValue[i]}`).join(',') + '}';
console.log(res);

As vlaz pointed out, you are creating neither a string or a new array, but an object. And just like maps, objects do not have a set order of keys in JavaScript. hence, there is quite a chance of getting another order in the object than in both arrays.

Related

Push JS Object to array overwrites existing objects [duplicate]

This question already has answers here:
Modifying a copy of a JavaScript object is causing the original object to change
(13 answers)
Closed 1 year ago.
I have this JS object:
baseFarm = {
name: "Farm",
tier: 1,
gridPos: 32,
}
and I want to push it to this array:
ownedLand = [];
This works perfectly, and if I console log this after the push I get:
Now, I want to push another another object to the same array, using that one as a base, however, I want the "gridPos" property to be different:
var newLand = baseFarm;
newLand.gridPos = parseInt( $('#purchaseLandPopupPlotNum').text() );
this.ownedLand.push(newLand);
However, after pushing this new object, the old one gets updated too:
What am I doing wrong?
Thanks in advance
You are assigning the same object to the new variable here:
var newLand = baseFarm;
So when you modify newLand, you are changing baseFarm aswell (and the object pushed to the array). And you are pushing the same object twice to the array.
Instead, you should clone baseFarm, either with Object.assign():
var newLand = Object.assign({}, baseFarm);
Or the more trendy spread operator:
var newLand = { ...baseFarm };
As an addendum, you could clone and modify the property on the same operation:
var newLand = Object.assign({}, baseFarm, { gridPos: parseInt( $('#purchaseLandPopupPlotNum').text() } );
In which case you wouldn't even need a new variable (or the baseFarm even, if it's always on the 0 index of the array):
this.ownedLand.push(Object.assign({}, this.ownedLand[0], { gridPos: parseInt( $('#purchaseLandPopupPlotNum').text() } ));
I'll let the spread version up to you :-)

how to create array of json object without key in javascript

I want to create an array of JSON object without a key.How can this is achieved ..??
for example [{8,0,2}, {20,0,2}].
var hh = 9
var mm = 8
var qty = 2
var data = [];
data.push({hh,mm,qty})
it gives data like [{hh:9,mm:8,qty:2}]
I want array like [{9,8,2},{9,3,4}]
You example uses a new feature of ECMAScript 6 that is the shorthand syntax for initialising object properties. This line in your example:
data.push({hh,mm,qty});
is equivalent to this verbose one:
data.push({hh: hh, mm: mm, qty: qty});
An object in JavaScript will always have keys and values. There is no way to save just values in a plain object. However, there are two other solutions.
One is using an array:
data.push([hh, mm, qty]);
Note the square brackets substituting the curly ones. This will obviously push an array of three values onto the data array. When retrieving the values, you can just refer to their index, as an array's items will always retain their indices:
var data2 = [hh, mm, qty];
var hh2 = data2[0];
var mm2 = data2[1];
var qty2 = data2[2];
Another way of just "saving the values" is using a set, though the construction of a Set object will still require passing it an array:
data.push(new Set([hh, mm, qty]));
Accessing the data is less straightforward in this case, as the set will typically only let you iterate it. Unlike similar data structures in other languages, a JavaScript set will retain the order of inserted values. It can therefore be safely converted into an array:
var mySet = new Set([hh, mm, qty]);
var data3 = Array.from(mySet);
var hh3 = data3[0];
var mm3 = data3[1];
var qty3 = data3[2];
You can read more about sets here.
You can wrap it over another JSON object with a key I assume you want a JSON object.
Like this { [{8,0,2}, {20,0,2}] } but this with a problem - It is not a valid JSON.
I had a similar problem for one of my scenario. Then I realised
A top level JSON can't exist without a key!
Consider this example, you have another KV pair in JSON and also this array.
{
"somekey" : "somevalue",
[ {8,0,2}, {20,0,2} ]
}
You can fetch "somevalue" with the key "somekey". But how would you access the array? you can't :(
I would suggest you to use a top level key for the JSON and make this array as value of it's. Example:
{
"my array" : [ {8,0,2}, {20,0,2} ]
}
Without a key value pair, the object was not created. That's why its adding a key using the variable name
Look at this error. Its invalid code
var a = [{8,0,2}, {20,0,2}];
console.log(a)
You could push to an array instead of an object
var data = [];
var hh = 9
var mm = 8
var qty = 2
var data = [];
data.push([hh,mm,qty])
console.log(data)
You can't.
Object Literal Property Value Shorthands allow you to create an object where the property names are inferred from the variable names you use to pass the data into.
If you don't have variable names, then there is nothing for the JS engine to use to figure out what the property names should be.
Consider using a function instead.
console.log([time(8,0,2), time(20,0,2)]);
function time (hh, mm, qty) {
return {hh, mm, qty};
}
The result you get at the end makes sense. By doing {hh,mm,qty} you are effectively saying "Use the variable name as the key and its value as the value". It might help us more if you provide an example of how you intend to use the result and access the variables i.e. the shape of the object you want in the end.
That being said, there are a couple alternatives:
Using values as the keys
If you really wanted your object to look similar to {8,0,2} you could use those values as the keys (all keys get converted to strings anyways) so you could do the following:
var example1 = {8:undefined,0:undefined,2:undefined};
var example2 = {8:null,0:null,2:null};
var keys = [];
for(var name in example1) {
keys.push(name);
}
// keys = ["8","0","2"];
var otherKeys = Object.keys(example2);
// otherKeys = ["8","0","2"];
Setting the keys dynamically
var hh = 9;
var mm = 8;
var qty = 2;
var obj = {};
obj[hh] = null;
obj[mm] = null;
obj[qty] = null;
//obj = {9:null,8:null,2:null};
I'm not certain if this solves your problem or answers your question entirely but it might give you some more insight into what is happening and why. The above examples are a common way to create a quick lookup versus a dictionary with would have values in place of null or undefined.

Access generated properties with unknown property names in array of objects [duplicate]

This question already has answers here:
How to get property value in js object when key is unknown
(3 answers)
Closed 3 years ago.
Using the following generated array example structure, how can I loop through and extract the property names and their associated values from each object?
[{"bg_2":"0.50"},{"bg_7":"0.10"},{"bg_12":"0.20"}]
The number of objects may change, and the property names will not be consistent.
You can use Object.keys()[0] to get the key, then use the key to get the value.
JSFiddle
var myData = [{"bg_2":"0.50"},{"bg_7":"0.10"},{"bg_12":"0.20"}];
for (var i = 0; i < myData.length; i++) {
var myObject = myData[i];
var firstKey = Object.keys(myObject)[0];
var value = myObject[firstKey];
console.log(firstKey + ": " + value);
}
See also: ECMAScript® Language Specification: 15.2.3.14 Object.keys ( O )
Expanding on #AR7's answer, in the case that there may be multiple properties in each of the objects you can cache the object returned by Object.keys() and loop through each property within the array loop.
Using the method below, you can handle any number of properties within the object.
I realize this may not be any more useful in this specific situation than the aforementioned answer, but hopefully it will be useful to future viewers.
JSFiddle
var a = [
{ "bg_2":"0.50", "bg_7":"0.10", "bg_12":"0.20"},
{ "bg_2":"0.50", "bg_7":"0.10"},
{ "bg_2":"0.50"}
];
a.forEach(function(o){
console.log(o);
var k = Object.keys(o);
for(var i in k)
console.log(k[i], ':', o[k[i]]);
});

Trying to add an array to an array if the array being added is not in the array already

what I am really trying to do is add an array after an event only if that event occurred once like the press of the enter button. if the user keeps on entering the wrong answer it should only update the array once with the array that represents the question. if you can help me out with this question that deals with more of what i am trying to do would be great.
if you cant help me with that i am wondering how to insert an array after an event only if the array isn't in the array. can you show me some code where you search for an array inside of an array and if that array is inside do something or nothing?
I don't understand why in the below code i am not able to search for arrays
function onlyUnique(value, index ,self){
return self.indexOf(value) === index;
}
var a = ['a' , [1], [1],'a']
var unique = a.filter(onlyUnique)
console.log(unique)
You could use an object like an associative array. You would need some way to identify the questions to link to the answers.
// answers storage
var answers = {};
// set answer to question 1, this would be replaced by automation
var questionId = 'q1';
var data = 'some answer';
// insert if not present
if(answers[questionId] === undefined) {
answers[questionId] = data;
}
// manipulate existing answer
else {
// do something with answers[questionId]
}
There is not a simple operation to do a deep comparison of objects. However, you can try converting the objects to JSON and comparing - provided the JSON generated has the objects properties in the same order then it will generate identical strings which can be compared:
function onlyUnique(a){
return a.map(function(v){ return JSON.stringify(v); })
.sort()
.filter(function(v,i,a){ return i==0 || v !== a[i-1]; })
.map(function(v){return JSON.parse(v);});
};
var a = ['a' , [1], [1],'a']
var unique = onlyUnique(a);
console.log(unique)

How to clone an array in javascript without using JSON.stringify or JSON.parse? [duplicate]

This question already has answers here:
Copy array by value
(39 answers)
Closed 8 years ago.
I have an array example fruit . I'd like to copy it as array fruits2, without keeping reference.
As in the following example reference is kept so fruits is modified.
var fruit = function (name){
this.name = name;
}
var fruits = [];
fruits.push(new fruit('apple'));
fruits.push(new fruit('banana'));
fruits.push(new fruit('orange'));
var fruits2 = fruits;
fruits2.length = 0;
console.log(fruits);
http://jsfiddle.net/vkdqur82/
Using JSON.stringify and JSON.parse does the trick but the objects in fruits2 are not any longer of type fruit but are of general type object
var temp = JSON.stringify(fruits);
var fruits2 = JSON.parse(temp);
I would like to know an alternative approach which would keep inner object of fruit.
Use slice: var fruits2 = fruits.slice(); should do it.
Your jsFiddle, modified
See also: MDN
**Edit. I was a bit lazy, let's correct my answer to make up for that.
For an Array of just values slice is perfect. For an Array of objects or arrays or a mix of values/objects/arrays, the Array and Object elements of the Array to clone need cloning too. Otherwise they will be references to the original arrays or objects (so: not copies) and a change of one [of these references of arrays or objects] will be reflected in all 'clones' containing a reference to it.
To clone an Array of Arrays/Objects/mixed values Array.map is your friend. There are several methods to think of:
creating a new instance with old data
var fruits1 = fruits.map(function(v) {return new Fruit(v.name);});
using JSON
var fruits2 = fruits.map(function(v) {return JSON.parse(JSON.stringify(v));});
create and use some cloning method
var fruits3 = fruits.map(function(v) {return cloneObj(v);});
In case 3, a method for cloning could look like:
function cloneObj(obj) {
function clone(o, curr) {
for (var l in o){
if (o[l] instanceof Object) {
curr[l] = cloneObj(o[l]);
} else {
curr[l] = o[l];
}
}
return curr;
}
return obj instanceof Array
? obj.slice().map( function (v) { return cloneObj(v); } )
: obj instanceof Object
? clone(obj, {})
: obj;
}
Using this cloneObj method, Array.map is obsolete.
You can also use var fruitsx = cloneObj(fruits);
The jsFiddle from the link above is modified to demonstrate these methods.
For Array.map, see again MDN
slice can do the trick.
You can also use .map but .slice is normally faster.
var copy = fruits.map(function(item) {return item});
Hope it helps
You can declare a new array and use concat method, so that you concat all values from your array to the new array. Something like this:
var x = ["a","b"];
var a = [];
a = a.concat(x);
console.log(a);
I edited my poor answer.
Best regards.

Categories