Reverse() doesn't work in array with string key - javascript

Why reverse() doesn't work if my array have elements with string as a key.
var myArray = [];
myArray["test"] = 100;
myArray["test2"] = 200;
console.log(myArray)
console.log(myArray.reverse())
Both returns the same result.
How can I change it to make it work?
DEMO: https://www.w3schools.com/code/tryit.asp?filename=GG4PXCHZ4VUD

.reverse() is a function of arrays, where elements are indexed by their position. Your code is not adding elements to the array, but rather adding properties on the array object. This works and the properties can be accessed, but reversing does nothing as these are not elements. The array is still of 0 length.
You will have to either:
Make myArray an object of a different type. In this case, reverse will still not work, and you will have to write code to sort manually. Other answers have provided some guidance as to how to achieve this
Add your elements to the array using push() or numeric indices, in which case you'll lose the string indices but can use array sorting methods such as .reverse()
While numbers have an intrinsic ordering, object property keys follow different rules. If you want to reverse a string-indexed object, consider writing a function to insert objects to a new Map in reverse order.

Arrays values are only accessible by index.
myArray[0] = 100;
myArray[1] = 200;
console.log(myArray) // [100, 200]
console.log(myArray.reverse()) // [200, 100]
You can store values by keys in objects.
var myObject = {};
myObject["test"] = 100;
myObject["test2"] = 200;
console.log(myObject) // {test: 100, test2: 200}
That said, you can reverse an object by doing this:
Object.entries(myObject).reverse().reduce((a, b) => {
a[b[0]] = b[1];
return a
},{})

Since you do not actually need any array methods, it would be better to simply use an object instead.
You can create a new reversed array by looping over Object.keys() backwards. See the code in action here.
var myArray = [];
myArray["test"] = 100;
myArray["test2"] = 200;
function reverseAssociative(arr){
const keys = Object.keys(arr);
const res = [];
for(let i = keys.length - 1; i >= 0; i--){
res[keys[i]] = arr[keys[i]];
}
return res;
}
const res = reverseAssociative(myArray);
for(const key in res){
console.log(key, res[key]);
}
You can simplify it by using reduce on Object.entries after reversing. See the code in action here.
myArray = Object.entries(myArray).reverse().reduce((acc,[key,val])=>(acc[key]=val,acc),[])

Related

JSON stringify does not convert array [duplicate]

In the example below, the array2.length is only 10, while in my mind, it should be 13.
Why does the "string keyed" indexes not increase the length of the array?
I can store things and still access it, and the VS debugger shows that those arrays are being stored properly. So why is the length not increased?
var array2 = new Array();
array2["a"] = new Array();
array2["b"] = new Array();
array2["c"] = new Array();
for (var i = 0; i < 10; ++i)
array2[i] = new Array();
var nothing = "";
for (var i = 0; i < array2.length; ++i)
nothing = "";
Javascript arrays cannot have "string indexes". A Javascript Array is exclusively numerically indexed. When you set a "string index", you're setting a property of the object. These are equivalent:
array.a = 'foo';
array['a'] = 'foo';
Those properties are not part of the "data storage" of the array.
If you want "associative arrays", you need to use an object:
var obj = {};
obj['a'] = 'foo';
Maybe the simplest visualization is using the literal notation instead of new Array:
// numerically indexed Array
var array = ['foo', 'bar', 'baz'];
// associative Object
var dict = { foo : 42, bar : 'baz' };
Because the length is defined to be one plus the largest numeric index in the array.
var xs = [];
xs[10] = 17;
console.log( xs.length ); //11
For this reason, you should only use arrays for storing things indexed by numbers, using plain objects instead if you want to use strings as keys. Also, as a sidenote, it is a better practice to use literals like [] or {} instead of new Array and new Object.
You're not adding items to the array; you're adding properties to the Array object.
As said above, use object for associative arrays.
If you don't you won't necessarily notice you're doing it wrong, until you innocently use "length" as an array index :
var myArray = [];
myArray["foo"] = "bar"; //works
console.log(myArray["foo"]) //print "bar"
myArray["length"] = "baz" //crash with a "RangeError: Invalid array length"
That is because you are replacing the length attribute of an array with a String, which is invalid.
"string keyed" indexes are not indexes at all, but properties. array2["a"] is the same as saying array2.a. Remember that you can set properties on any kind of variable in javascript, which is exactly what you're doing here.
You can push object to array, it will automatically get indexed (integer). If you want to add index as you want then you want to make it as object
If you want to use an object's properties as if they were like instances of a string indexed array, the work around for the length is:
var myArray = new Array();
myArray["a"] = 'foo';
myArray["b"] = 'bar';
myArray["c"] = 'baz';
let theLength = Object.keys(myArray).length

Is it okay to loop functions in JavaScript?

Is there any kind of built-in method that would iterate through the object parameters without loop. Like the array object has methods(forEach, sort, filter..).
For example there's an array
var numbers = [3,342,23,22,124];
var max = 0;
for(var i=0;i<numbers.length;i++){
if(numbers[i] > max){
max = numbers[i];
}
}
alert(max);
Instead of looping sort() method could be used
var numbers = [3,342,23,22,124];
numbers.sort(function(a,b){return b - a});
alert(numbers[0]);
Is there any method for regular objects {} in JavaScript, that would work the same way as sort()?
More generally is there any way to avoid such looping:
for(var parameter in object){
var data = object[parameter]
exampleMethod(data);
}
is there a way to execute a function several times without looping?
No, but you can often use a function like Object.keys() to open a pathway to the Array prototype methods like .forEach().
The Object.keys() method returns an array with the "own" property names of an object. (The "own" names are the names of properties directly on the object, and not inherited from the prototype chain.) From there, you can use the Array methods like .forEach to iterate through the property names and, by using those to reference the object, through the property values as well.
For example, consider this object:
var dimensions = {
length: 20,
height: 30,
width: 40
};
If you wanted to sum up the edges, you could do this:
var perimeter = Object.keys(dimensions).reduce(function(sum, dkey) {
sum += 4 * dimensions[dkey];
return sum;
}, 0);
Note also the related methods Object.getOwnPropertyNames() and Object.getOwnPropertySymbols(), which expand the properties available for iteration.
Not like sort because there is no order of properties in JavaScript objects. However, you can use Object.keys and map to turn an object into an array of values.
var o = {a:1,b:3, c, :2};
var arr = Object.keys(o).map(key=>o[key]).sort((a,b)=>b-a);
var max = arr[0];
For regular iteration, combine keys and forEach
Object.keys(o).forEach(key=>console.log('key',key, 'value', o[key]));

How to convert Set to Array?

Set seems like a nice way to create Arrays with guaranteed unique elements, but it does not expose any good way to get properties, except for generator [Set].values, which is called in an awkward way of mySet.values.next().
This would have been ok, if you could call map and similar functions on Sets. But you cannot do that, as well.
I've tried Array.from, but seems to be converting only array-like (NodeList and TypedArrays ?) objects to Array. Another try: Object.keys does not work for Sets, and Set.prototype does not have similar static method.
So, the question: Is there any convenient inbuilt method for creating an Array with values of a given Set ? (Order of element does not really matter).
if no such option exists, then maybe there is a nice idiomatic one-liner for doing that ? like, using for...of, or similar ?
if no such option exists, then maybe there is a nice idiomatic
one-liner for doing that ? like, using for...of, or similar ?
Indeed, there are several ways to convert a Set to an Array:
Using Array.from:
Note: safer for TypeScript.
const array = Array.from(mySet);
Simply spreading the Set out in an array:
Note: Spreading a Set has issues when compiled with TypeScript (See issue #8856). It's safer to use Array.from above instead.
const array = [...mySet];
The old-fashioned way, iterating and pushing to a new array (Sets do have forEach):
const array = [];
mySet.forEach(v => array.push(v));
Previously, using the non-standard, and now deprecated array comprehension syntax:
const array = [v for (v of mySet)];
via https://speakerdeck.com/anguscroll/es6-uncensored by Angus Croll
It turns out, we can use spread operator:
var myArr = [...mySet];
Or, alternatively, use Array.from:
var myArr = Array.from(mySet);
Assuming you are just using Set temporarily to get unique values in an array and then converting back to an Array, try using this:
_.uniq([])
This relies on using underscore or lo-dash.
Perhaps to late to the party, but you could just do the following:
const set = new Set(['a', 'b']);
const values = set.values();
const array = Array.from(values);
This should work without problems in browsers that have support for ES6 or if you have a shim that correctly polyfills the above functionality.
Edit: Today you can just use what #c69 suggests:
const set = new Set(['a', 'b']);
const array = [...set]; // or Array.from(set)
Use spread Operator to get your desired result
var arrayFromSet = [...set];
The code below creates a set from an array and then, using the ... operator.
var arr=[1,2,3,4,5,6,7,8,9,1,2,3,4,5,6,7,8,9,];
var set=new Set(arr);
let setarr=[...set];
console.log(setarr);
SIMPLEST ANSWER
just spread the set inside []
let mySet = new Set()
mySet.add(1)
mySet.add(5)
mySet.add(5)
let arr = [...mySet ]
Result: [1,5]
In my case the solution was:
var testSet = new Set();
var testArray = [];
testSet.add("1");
testSet.add("2");
testSet.add("2"); // duplicate item
testSet.add("3");
var someFunction = function (value1, value2, setItself) {
testArray.push(value1);
};
testSet.forEach(someFunction);
console.log("testArray: " + testArray);
value1 equals value2 => The value contained in the the current position in the Set. The same value is passed for both arguments
Worked under IE11.
Using Set and converting it to an array is very similar to copying an Array...
So you can use the same methods for copying an array which is very easy in ES6
For example, you can use ...
Imagine you have this Set below:
const a = new Set(["Alireza", "Dezfoolian", "is", "a", "developer"]);
You can simply convert it using:
const b = [...a];
and the result is:
["Alireza", "Dezfoolian", "is", "a", "developer"]
An array and now you can use all methods that you can use for an array...
Other common ways of doing it:
const b = Array.from(a);
or using loops like:
const b = [];
a.forEach(v => b.push(v));
the simplistic way to doing this
const array = [...new Set([1,1,2,3,3,4,5])]
console.log(array)
Here is an easy way to get only unique raw values from array. If you convert the array to Set and after this, do the conversion from Set to array. This conversion works only for raw values, for objects in the array it is not valid. Try it by yourself.
let myObj1 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
let myObj2 = {
name: "Dany",
age: 35,
address: "str. My street N5"
}
var myArray = [55, 44, 65, myObj1, 44, myObj2, 15, 25, 65, 30];
console.log(myArray);
var mySet = new Set(myArray);
console.log(mySet);
console.log(mySet.size === myArray.length);// !! The size differs because Set has only unique items
let uniqueArray = [...mySet];
console.log(uniqueArray);
// Here you will see your new array have only unique elements with raw
// values. The objects are not filtered as unique values by Set.
// Try it by yourself.
I would prefer to start with removing duplications from an array and then try to sort.
Return the 1st element from new array.
function processData(myArray) {
var s = new Set(myArray);
var arr = [...s];
return arr.sort((a,b) => b-a)[1];
}
console.log(processData([2,3,6,6,5]);
function countUniqueValues(arr) {
return Array.from(new Set(arr)).length
}
console.log(countUniqueValues([1, 2, 3, 4, 4, 4, 7, 7, 12, 12, 13]))

creating multi-dim arrays (JS)

I was trying to create a 3-dimensional array and couldn't find an easy way to do it.
array = [[[]]];
or
array = [][][];
or
array = []; array[] = []; array[][] = [];
would for example not work. (the console'd say the second array is 'undefined' and not an object, or for the second and third example give a parse error).
I cannot hard-code the information either, as I have no idea what the indexes and contents of the array are going to be (they are created 'on the fly' and depending on the input of a user. eg the first array might have the index 4192). I may have to create every array before assigning them, but it would be so much easier and faster if there's an easier way to define 3-dimensional arrays. (there'll be about 2 arrays, 25 subarrays and 800 subsubarrays total) every millisecond saves a life, so to say.
help please?
JavaScript is dynamically typed. Just store arrays in an array.
function loadRow() {
return [1, 2, 3];
}
var array = [];
array.push(loadRow());
array.push(loadRow());
console.log(array[1][2]); // prints 3
Since arrays in javascript aren't true arrays, there isn't really a multidimensional array. In javascript, you just have an arrays within an array. You can define the array statically like this:
var a = [
[1,2,3],
[4,5,6],
[7,8,9]
];
Or dynamically like this:
var d = [];
var d_length = 10;
for (var i = 0;i<d_length;i++) {
d[i] = [];
}
UPDATE
You could also use some helper functions:
function ensureDimensions(arr,i,j,k) {
if(!arr[i]) {
arr[i] = [];
}
if(!arr[i][j]) {
arr[i][j] = [];
}
}
function getValue(arr,i,j,k) {
ensureDimensions(i,j,k);
return arr[i][j][k];
}
function setValue(arr,newVal,i,j,k) {
ensureDimensions(i,j,k);
arr[i][j][k] = newVal;
}

How to use push with sub-arrays?

I have 3 arrays like:
var arr1 = [];
var arr2 = [];
var arr3 = [];
//When I want to add something into array then I use
arr1.push("text");
arr2.push("text");
but is it possible to make something like the following example?
//example:
var arr = [];
arr['group1'].push("text1");
arr['group2'].push("text2");
arr['group2'].push("textn");
//and then iterate like:
for(item in arr['group1'])
console.log(item);
is it even possible to do something like that? I have tried but does not work.
There's a fundamental misunderstanding though, arr is an array but you're using it as an associative array, which in JavaScript is better represented with an object {}. for...in is for objects, NOT arrays, the MDN has a warning note about it:
for..in should not be used to iterate over an Array where index order
is important...
I would advice even if index is trivial to use a regular for loop or a forEach.
Consider using the following, more appropiate approach.
var obj = {
group1: ['text1'],
group2: ['text2'],
group3: ['text3']
};
// pushing more strings
obj.group1.push('foo');
obj['group2'].push('baz');
You're treating arr['group1'] as an array (by using .push()), but you haven't declared it as an array.
var arr = [];
arr['group1'] = [];
arr['group2'] = [];
arr['group3'] = [];
arr['group1'].push("text1");
arr['group2'].push("text2");
arr['group2'].push("textn");
It seems you're actually looking for Javascript Objects instead of arrays.
Also, you need to create these objects first.
var obj = {group1:[],group2:[],group3:[]};
/* or
var obj = {};
obj.group1 = [];
*/
obj['group1'].push("text1");
// or obj.group1.push("text1");
The for...in structure sets your for variable to the key, not the value. Assuming arr['group1'] is an array, this will work fine:
//example:
var arr = [];
arr['group1'].push("text1");
arr['group2'].push("text2");
arr['group2'].push("textn");
//and then iterate like:
for(item in arr['group1'])
console.log(arr['group1'][item]);​

Categories