Copy array N times to a flatted array - javascript

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

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

Merging multiple arrays inside a array of objects into a single array

I have a object where data is an array of objects, inside data object I have one users property which is an array.
I need to get all the users into a single array. I have written using map and concat.
Is there any way I can have a better solution, or this is correct?
See the below snippet.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var users = response.data.map(o => o.users)
const usersCollection = [].concat(...users)
console.log(usersCollection)
You can use Array.prototype.flat():
The flat() method creates a new array with all sub-array elements concatenated into it recursively up to the specified depth.
depth | Optional
The depth level specifying how deep a nested array structure should be flattened. Defaults to 1.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var users = response.data.map(o => o.users).flat();
console.log(users);
You can also try with Array.prototype.flatMap() which is identical to a map followed by a call to flat of depth 1.
var users = response.data.flatMap(o => o.users);
If Using ES6, utilizing the power of spread with Array.reduce
var response = {
data: [{
users: [1, 2, 3]
}, {
users: [4, 5, 6]
}]
}
var users = response.data.reduce((accumulator, obj) => [...accumulator, ...obj.users], []);
console.log(users);
Using ES6 Spread operator you can do the job quick.
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
let wantedArray = [];
for(let v of response.data){
wantedArray.push(...v.users);
}
console.clear();
console.log(wantedArray);
The flatMap() method first maps each element using a mapping function,
then flattens the result into a new array. It is identical to a map
followed by a flat of depth 1, but flatMap is often quite useful, as
merging both into one method is slightly more efficient
response.data.flatMap(({users})=>users)
You should be careful with vendor support though if you’re running in the browser.
You can use ES6 spread operator
var response = {data: [{users: [1,2,3]}, {users: [4,5,6]}]}
var NEWARRAY = [];
for(var v of response.data){
NEWARRAY.push(...v.users);
}
console.log(NEWARRAY);

Array.reduce() on an array of objects -- getting back strings of single letters

I'm working to understand Array.reduce() in JavaScript. I have an array of objects that I'm trying to apply .reduce() to, but I'm getting back an array of single letter strings.
Goal:
["Stuff", "necklace", "ring", "bracelet"]
Current Array of Objects
const productArray =
[
{
id: 1,
productTitle: "Necklace"
},
{
id: 2,
productTitle: "Ring"
},
{
id: 3,
productTitle: "Bracelet"
}
]
Function call
const newStuff = productArray.reduce(function(a, currentValue) {
return [...a, ...currentValue.productTitle];
}, ["Stuff"])
Actual result:
What do I need to do to specify that I don't want "productTitle" broken down into single-letter strings? I have been looking for resources regarding .reduce() on an array of objects but I haven't found anything very helpful. Any pointers?
To concatenate an array and value when using spread to create a new array, you spread the previous array to the new array, and add the new item without spreading it.
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.reduce((a, currentValue) =>
[...a, currentValue.productTitle], []);
console.log(newStuff);
In this case, it's better to use Array.map():
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.map((currentValue) => currentValue.productTitle);
console.log(newStuff);
Do not spread the title, pass it as it is:
const newStuff = productArray.reduce(function(a, currentValue) {
return [...a, currentValue.productTitle];
}, ["Stuff"]);
...currentValue.productTitle spreads into an array of individual letters, you only want to spread a variable, the aggregate here.
Basically a string is iterable, because the iterator is implemented and returns an array of single characters, if using spread syntax ....
Spread syntax allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.
console.log([...'foo']);
Other answers have pointed out why your code is wrong. But I do want to also note that what you're doing is already covered by Array.prototype.concat:
const productArray = [{"id":1,"productTitle":"Necklace"},{"id":2,"productTitle":"Ring"},{"id":3,"productTitle":"Bracelet"}];
const newStuff = productArray.reduce((a, val) => a.concat(val.productTitle), ['Struff']);
console.log(newStuff);
(And of course, as another answer has mentioned, this sounds more like a use for map than reduce, which might not matter since you're using this to learn reduce.)
The use of spread in this case is unnecessary and inefficient as it creates a new accumulator array from the previous one on every iteration. You can remove spread (and fix your issue) and use concat instead to keep it as a one-liner.
However, since you're just adding one new value on each iteration, you should use push. It requires one more line of code but is likely more efficient than using concat.
var productArray = [{id: 1,productTitle: "Necklace"},
{id: 2,productTitle: "Ring"},
{id: 3,productTitle: "Bracelet"}
];
// Using concat
var newStuff = productArray.reduce((acc, value) =>
acc.concat(value.productTitle),
["Stuff"]);
console.log(newStuff);
// Using push
var newStuff = productArray.reduce((acc, value) => {
acc.push(value.productTitle);
return acc;
}, ["Stuff"]);
console.log(newStuff);

2-dimensional arrays in ES6

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

es6 unique array of objects with set

I came across this example for creating unique arrays with es6
[ ...new Set(array) ]
Which seems to work fine until I tried it with an array of objects and it didn't return unique array.
i.e.
let item = [ ...new Set([{id:123,value:'test'},{id:123,value:'test'}]) ];
Why is that ?
you can try to do
uniqueArray = a => [...new Set(a.map(o => JSON.stringify(o)))].map(s => JSON.parse(s))
I know its ugly as hell but in most cases works apart from where you have new Date() in your object param then that on stringify be converted to ISO string.
so then do
let arr = [{id:1},{id:1},{id:2}];
uniqueArray(arr) //[{id:1},{id:2}]
Why is that ?
As per documentation
The Set object lets you store unique values of any type, whether
primitive values or object references.
Now reference for each of those arrays inside that Set constructor will be different so they are not considered to be a unique value by the constructor.
This will work:
let objectReference = {id:123,value:'test'}
let uniqueArray = [...new Set([objectReference, objectReference])]
>> [{id:123,value:'test'}]
What you're doing:
let objRef1 = {id:123,value:'test'} // creates a reference to a location in memory
let objRef2 = {id:123,value:'test'} // creates a new reference to a different place in memory
let uniqueArray = [...new Set([objRef1, objRef2])]
>> [{id:123,value:'test'},{id:123,value:'test'}]

Categories

Resources