2-dimensional arrays in ES6 - javascript

Long story short, i'm looking for a way to create and fill 2D arrays using ES6, in an effort to avoid for loops. The created array should contain all 0s. I've tried many different approaches so i cant post all of them.
var [r, c] = [5, 5];
var m = Array(r).fill(Array(c).fill(0));
This works but it creates a bunch of instances of the same array, and adding slice Array(r).fill(Array(c).fill(0).slice()); doesn't help either.
I also tried creating the empty arrays and then looping trough them but that's a whole different problem, you apparently can't forEach() or map() an empty array, and i couldn't even loop through a filled one efficiently.
Am i missing something here? Are a whole lot of for loops the best way to approach this? It looks really messy and overly long. Any help appreciated.

Doing this worked for me:
var [r, c] = [5, 5];
var m = Array(r).fill().map(()=>Array(c).fill(0));
Basically just filling it with a dummy value so you can map over it

You could use Array.from that takes a callback function and inside return arrays with 0's using fill method.
const arr = Array.from(Array(2), () => Array(5).fill(0))
console.log(arr)
Or you could just create array where each element is number of elements in sub-array and then use map and fill methods.
const arr = [5, 5].map(e => Array(e).fill(0))
console.log(arr)

For those needing the same thing but with undefined as each value this also works.
const x = 100;
const y = 100;
const grid = [...new Array(x)].map(() => [...new Array(y)]);
To fill the array simply map the inner value.
This will make an array filled with 0 for each value.
const x = 100;
const y = 100;
const grid = [...new Array(10)].map(() => [...new Array(10)].map(() => 0));

const nthArray = (n) => Array.from(Array(n), () => Array(5).fill(0))
const arr = nthArray(3);
console.log(arr);

Related

Set and spread operator [duplicate]

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]))

Array 'map' vs 'forEach' - functional programming

I have an array of objects:
let reports = [{ inbound_calls: [...], outbound_calls: [...], outbound_national_calls: [...] },...];
What is the best way to create a new array and assign into a variable:
1st approach - one loop:
let inbound_calls = []; outbound_national_calls = [], outbound_calls = [];
reports.forEach((e) => {
inbound_calls.push(e.inbound_calls);
outbound_national_calls.push(e.outbound_national_calls);
outbound_calls.push(e.outbound_calls);
})
2nd approach:
let inbound_calls = this.reports.map((report) => report.inbound_calls)
let outbound_national_calls = this.reports.map((report) => report.outbound_national_calls)
let outbound_calls = this.reports.map((report) => report.outbound_calls)
I'm starting to learn functional programming, and want to apply it to my code, I would go with first approach (one loop), but as I did research about functional programming I think the second one is the right way (much cleaner) but, I'm not sure, what is less expensive operation?
If your ultimate goal is to create three variables out of the object, you may use object destructuring as follows. No loops required.
let reports = {
inbound_calls: [1, 2, 3],
outbound_calls: [4, 5, 6],
outbound_national_calls: [7, 8, 9]
};
let {inbound_calls, outbound_calls, outbound_national_calls} = reports;
console.log(inbound_calls);
console.log(outbound_calls);
console.log(outbound_national_calls);
If you want to copy the arrays, just use Array#slice (the 0 passed is optional as it is the default start index so you can omit it if you want) like:
let inbound_calls = reports.inbound_calls.slice(0),
outbound_national_calls = reports.outbound_national_calls.slice(0),
outbound_calls = reports.outbound_calls.slice(0);
or Array.from like:
let inbound_calls = Array.from(reports.inbound_calls),
outbound_national_calls = Array.from(reports.outbound_national_calls),
outbound_calls = Array.from(reports.outbound_calls);
What you're essentially doing is a matrix transposition:
const report = (inbound_calls, outbound_calls, outbound_national_calls) =>
({ inbound_calls, outbound_calls, outbound_national_calls });
const reports = [report(1,2,3), report(4,5,6), report(7,8,9)];
const transpose = reports =>
report( reports.map(report => report.inbound_calls)
, reports.map(report => report.outbound_calls)
, reports.map(report => report.outbound_national_calls) );
console.log(transpose(reports));
Now, depending upon your application the fastest way to transpose a matrix might be not to transpose it at all. For example, suppose you have a matrix A and its transpose B. Then, it holds that for all indices i and j, A[i][j] = B[j][i]. Consider:
const report = (inbound_calls, outbound_calls, outbound_national_calls) =>
({ inbound_calls, outbound_calls, outbound_national_calls });
const reports = [report(1,2,3), report(4,5,6), report(7,8,9)];
// This is equivalent to transpose(reports).outbound_calls[1]
const result = reports[1].outbound_calls;
console.log(result);
That being said, your second approach is IMHO the most readable.

JS: Print main diagonal of array using array methods

How to print the main diagonale of array without using cycle for(...) but using array methods instead?
const arr = [
[1,6,8,-1],
[0,2,-6,5],
[0,-5,3,6],
[9,-1,1,0] ];
Here elements arr[0][0] = 1, arr[1][1]=2, arr[2][2]=3, arr[3][3]=0 are elements of the main diagonale. We can print them using cycle for:
for (let i=0;i<arr.length;i++)
{
console.log(arr[i][i]);
}
But is there a possibility to print them using methods .forEach .map or another one?
You can use Array.prototype.map but essentially they use the loops inside:
var a = [
[1,6,8,-1],
[0,2,-6,5],
[0,-5,3,6],
[9,-1,1,0] ];
var r = a.map((v, i) => v[i]);
console.log(r);
You can use array methods to get the same result, but they use for-loops inside anyways and in this case a single for-loop looks more readable to me.
However, if you really wanted to, you could do it like so:
const arr = [
[1,6,8,-1],
[0,2,-6,5],
[0,-5,3,6],
[9,-1,1,0] ];
const result = arr.map((sub_array, index) => sub_array.filter((number, index2) => index === index2));
console.log(result);

Copy array N times to a flatted array

I've an array of four elements and I want to copy it to another array four times and I've done it by concatenating four times.
My efforts
let demoProperties = []
.concat(fourDemoProperties)
.concat(fourDemoProperties)
.concat(fourDemoProperties)
.concat(fourDemoProperties);
I also followed another way (map and reduce) but this way iterate two times.
Have there any easiest optimum way to copy N times? Any of your suggestions will be appreciated.
You can use the spread syntax:
const demoProperties = [...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties];
Or use Array#fill to duplicate the array, and then use spread syntax with Array#concat to get a new array:
const fourDemoProperties = [1, 2, 3, 4];
const demoProperties = [].concat(...Array(4).fill(fourDemoProperties));
console.log(demoProperties);
Note: both the manual an the Array#fill are shallow clones. If the items are objects, you'll clone the reference to the objects, and if you'll change one of them, the "copies" will change as well.
Example (check the browser's console):
const fourDemoProperties = [{ a: 1 }, { b: 2 }];
const demoProperties = [...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties, ...fourDemoProperties];
demoProperties[0].a = 5000;
console.log(demoProperties);
How you do it depend if you want to keep the reference among the sub arrays or not.
var ar = [1,2,3,4],
ars = Array.from({length:4}).map(_ => ar),
brs = Array.from({length:4}).map(_ => ar.slice());
console.log(ars);
console.log(brs);

How to get the difference between two arrays?

I have 2 arrays:
arr1 = [[11,12],[11,13],[11,14], [12,13]];
arr2 = [[11,13],[11,14]];
Expected result [[11,12],[12,13]].
How can I get the difference between the two arrays? I use lodash _.difference but it gives me a wrong answer.
You need to use _.differenceWith(), because you need to compare the elements of the sub-arrays. By default, it just tests whether the sub-arrays are the same objects, which they presumably aren't.
result = _.differenceWith(arr1, arr2, _.isEqual);
Using just javascript, and only for this and similar examples
var a1 = [[11,12],[11,13],[11,14], [12,13]];
var a2 = [[11,13],[14,11]];
var a3 = a1.filter(ar1 => !a2.some(ar2 => ar1.every(n1 => ar2.includes(n1))))
console.log(a3); // [[11,12],[12,13]]
There are too many criteria to create a generic solution.
For example is [11,12] the same as [12,11], maybe only references to the same array are the same, (ar1 === ar2) as true. What if there are two identical entries in the same array and one in the other, do you filter one out, or keep it? The number of questions can go on for some time and it gets worse the deeper the nesting and the greater the number of types stored in the array.
var a1 = [[11,12],[11,13],[11,14], [12,13]]
var a2 = [[11,13],[14,11],[12,14]];
a3 = [];
[[a1,a2],[a2,a1]].forEach(a=>{
a3.push(...a[0].filter(
ar1 => !a[1].some(
ar2 => ar1.every(
n1 => ar2.includes(n1)
)
)
))
});
console.log("[["+a3.join("], [")+"]]")
Just a few lines of pure JS is sufficient for this separation (union') job. Besides you should make sure to check both arrays over the other.
var arr1 = [[11,12],[11,13],[11,14],[12,13]],
arr2 = [[11,13],[11,14],[12,14]];
res = arr1.reduceRight((p,c,i,a) => { var fi = p.findIndex(s => c.every(n => s.includes(n)));
return fi !== -1 ? (a.splice(i,1),
p.splice(fi,1),
p)
: p;
},arr2)
.concat(arr1);
console.log(res);
You could do it without lodash. The tip woud be to map subarrays into strings to make comparison easy
var arr1 = [[11,12],[11,13],[11,14], [12,13]];
var arr2 = [[11,13],[11,14],[12,14]];
var res = arr1.concat(arr2).map(x => x.join(",")).filter((x,i,arr) => arr.indexOf(x) === arr.lastIndexOf(x)).map(x => x.split(","));
console.log(res);

Categories

Resources