Convert 2D nested array into 1D array in JavaScript? - javascript

Given a 2D array as shown in the example, how to manage to combine the string digits into one.
ex: Array2 = [[1,2,3],[4,5,6],[7,8,9]];
required sol:
Array1 = [123, 245, 789];

You can deconstruct your task into two separate problems, that we will solve in turn.
We need to take an array of numbers (e.g. [1, 2 ,3]) and join them together into a string (e.g. '123').
There is, in fact, a dedicated function for this in JavaScript - the join() function:
[1, 2, 3].join(''); // '123'
We need to perform the previous function on each object in an array, returning an array of the transformed objects.
JavaScript again has you covered, this time with the map() function:
[a, b, c].map((element) => foo(element)); // [foo(a), foo(b), foo(c)]
All we have to do now is join these too together, so that the operation we perform on each element of the parent array, is to join all of the child elements together:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]].map((array) => array.join('')); // ['123', '456', '789']

function foo(arr){
let toReturn = [];
for(let i = 0;i < arr.length;i++){
toReturn.push(arr[i].join(""));
}
return(toReturn);
}
console.log(foo([[1,2,3],[4,5,6],[7,8,9]]));

You can use reduce to aggregate your data combined with .join('') to get all element items of each array item into a single value like below:
const data = [[1,2,3],[4,5,6],[7,8,9]];
const result = data.reduce((acc, curr) => {
acc.push(curr.join(''));
return acc;
}, []);
console.log(result);

Return all files as a 1D array from given path
const fetchAllFilesFromGivenFolder = (fullPath) => {
let files = [];
fs.readdirSync(fullPath).forEach(file => {
const absolutePath = path.join(fullPath, file);
if (fs.statSync(absolutePath).isDirectory()) {
const filesFromNestedFolder = fetchAllFilesFromGivenFolder(absolutePath);
filesFromNestedFolder.forEach(file => {
files.push(file);
})
}
else return files.push(absolutePath);
});
return files
}

Related

React: Add values from array in another array

I'm trying to do this kind of operation but I don't understand how to do.
I have two array:
array1 = [elem1, elem2, elem3]
and a second array:
array2 = [elemA, elemB, elemC]
What i would to obtain is:
arrayFinal = [elem1:elemA, elem2:elemB, elem3:elemC]
How can I do??
Thank you so much.
EDIT:
the arrayFinal is not key:value, but the elem1:elemA is only the first value, elem2:elemB is the second value, for example using a join.
EDIT2:
I make an example of valure of array:
array1 = [0, 20, 40, 60, 80]
array2 = [-97:61:-1008; -97:60:-1008; -97:73:-1006, -98:70:-1008]
arrayFinal = [0:-96:61:-1009, 20:-97:61:-1008, 40:-97:60:-1008, 60:-97:73:-1006, 80:-98:70:-1008]
I See that there is a lot of confusion going on in the answers/comments, some people think you want to combine the arrays into key/value pairs, while others think you want to concat the arrays, while others think you want to make it an array where array1 is the index and array2 is the value at that index.
This is all caused by your formatting of [Elem1:ElemA, Elem2:ElemB]. which isnt even valid JS as far as i am aware.
However you edited your question, and now it seems like you want to combine them like [[Elem1, ElemA], [Elem2, ElemB]] in which case you can do that really easily in this way:
const array1 = ["elem1", "elem2", "elem3"];
const array2 = [1, 2, 3];
const result = array1.map((key, i) => [key, array2[i]]);
this will yield the result: [ [ 'elem1', 1 ], [ 'elem2', 2 ], [ 'elem3', 3 ] ]
You can do it like this:
const array1 = [0, 20, 40, 60, 80];
const array2 = ["-97:61:-1008;", "-97:60:-1008;", "-97:73:-1006", "-98:70:-1008"];
const arrayFinal = array1.map((item,index) => `${item}:${array2[index]}`);
If you are sure both arrays have the same length you can loop through the first one with a map and do something like that:
const arrayFinal = array1.map((item, i) => ({[item]: array2[i]}));
You'll get:
arrayFinal = [{elem1: elemA}, {elem2: elemB}...]
const array1 = ['item1', 'item2', 'item3'];
const array2 = [1, 2, 3];
const arrayFinal = array1.map((item, i) => ({[item]: array2[i]}));
console.log(arrayFinal);
Your case is very close to the following utility functions:
https://lodash.com/docs/4.17.15#zip
https://ramdajs.com/docs/#zip
Also, it could be implemented as follows:
function zip<A, B>(listA: A[], listB: B[]): Array<[A, B]> {
return listA.map((a, i) => [a, listB[i]]);
}
https://www.typescriptlang.org/play?#code/GYVwdgxgLglg9mABALxgBwDwEEA0iBCAfABQA2MAzlFgFyJYDaAunuVfnfswJR1YBO-AIYBPDA1wEmhRAG8AUIkT8AplBD8kbagDoAtkLTFiQvDG6IAvDIanE2rjCZNuAbnkBfefIgIKcUhUdUjgAc2JUIwYARhwAJhwAZhZEBgAWHABWHAA2FzcgA
If you want a dictionary:
function zipObject<A extends (string | number | symbol), B>(listA: A[], listB: B[]): { [key in A]: B } {
return Object.assign(
{},
...listA.map((a, i) => ({ [a]: listB[i] })),
);
}

How to know if an array is single dimension or multiple dimension?

I need your help arround array in JS.
I have a function where i need to check if the array passed in argument is one dimension or 2 dimension
let's say :
function test(array){
if(array is single dimension{
console.log("Single dimension");
}else{
console.log("2Dimension");
and the following should display :
test([1,2,3]); // Should log "Single dimension"
test([[1,2,3],[1,2,3]]); // Should log "2Dimension"
Any help will be really nice! Thank you!
How to know if an array is single dimension or multiple dimension?
JavaScript doesn't have multi-dimensional arrays; it has arrays of arrays. There's a subtle difference between those two things. Even more, a JavaScript can have entries that are arrays and other entries that aren't arrays, making it only partially "multi-dimensional."
If you need to know that an array doesn't contain any arrays (e.g., is one-dimensional), the only way is to check every entry in it to see if that entry is an array:
if (theArray.every(entry => !Array.isArray(entry)) {
// One dimensional
} else {
// Has at least one entry that is an array
}
Here's an example of an array that only has some entries that are arrays and others that aren't:
const a = [1, 2, ["a", "b"], 3];
console.log(a.length); // 4, not 5
console.log(Array.isArray(a[0])); // false
console.log(Array.isArray(a[2])); // true
You could take a recursive approach and check the first element for nested arrays.
function getDimension([array]) {
return 1 + (Array.isArray(array) && getDimension(array));
}
console.log(getDimension([1, 2, 3]));
console.log(getDimension([[1, 2, 3], [1, 2, 3]]));
Related to this one
Get array's depth in JavaScript
You can use function like this one :
function getArrayDepth(value) {
return Array.isArray(value) ?
1 + Math.max(...value.map(getArrayDepth)) :
0;
}
Then simply
const testArray = [1,2,3];
if (getArrayDepth(testArray) > 1){
console.log('One array');
}else{
console.log('Array in array')
}
It can be checked like that:
const arr = [1, 2, 3];
const multiDimensional = [
[1,2,3],
[1,2,3]
];
const isMultiDimensional = (arr) => {
const result = arr.reduce((a, c) => {
if (c.constructor === Array)
a = true;
return a;
}, false)
return result;
}
console.log(isMultiDimensional ([1, 2, 3]));
console.log(isMultiDimensional ([[1, 2, 3], [1, 2, 3]]));

Merge multiple arrays together if not null

I am building a React App and am using Async Actions to make request to outside API's and bring in data into my app. I have 4 arrays that I need to merge together. Since I am using Async Actions the default values if theres no data is null. I want to check to see if the array is not null and if it has a value then merge it with the others into a single array. Once I have all the data into a single array I am going to use the includes method to see if any of the values are present in the array. Using the spread operator I don't think is going to work here as it will fail as null is not an iterable. Is there a way to do this with reduce to check through each of the 4 separate arrays make sure the value is not null and then combine them together into one array.
Your question leads you to the answer. :)
Essentially you are asking how to filter all non-array inputs and then combine (or concatenate) them together into a new array.
A couple of notes on the following approach:
For better stability in filtering, rather than using a blacklist (not null), use a whitelist (Array.isArray) to ensure only arrays are combined.
The spread operator can be used to then create an arguments list for a new array's concat method.
const arr1 = [1,2];
const arr2 = null;
const arr3 = [3,4];
const arr4 = [5];
const concat = (...arrays) => [].concat(...arrays.filter(Array.isArray));
console.log(concat(arr1, arr2, arr3, arr4));
For a bit of fun, if the combined array needs to be unique values (assuming simple types for values) then including a quick cast to a Set and back to an Array can make that happen:
const arr1 = [1,2];
const arr2 = null;
const arr3 = [3,4];
const arr4 = [4,5];
const concat = (...arrays) =>[].concat(...arrays.filter(Array.isArray));
const unique = (array) => [...new Set(array)];
const concated = concat(arr1, arr2, arr3, arr4);
const uniqued = unique(concated);
console.log({concated, uniqued});
Here is a one line solution (ES6).
At the first part, we merge all arrays, and then filter array elements - we include only "not null" values and exclude duplicates:
const arr1 = [1, null, 6, 'q'],
arr2 = null,
arr3 = [1, 1, null, 1],
arr4 = ['e', 'q', 6, 1, null];
const final = []
.concat(arr1, arr2, arr3, arr4)
.filter((item, i, arr) => item && arr.indexOf(item) === i);
console.log(final); // Expected output: [1, 6, "q", "e"]
var a = [1, 2, 3]
var b = null
var c = [...a||[], ...b||[]]
console.log(c)
If you assign your arrays to properties of an object obj, you can simply iterate over the object :
const a = ["a", "1"], b = null, c = ["c", 78], d = []
const obj = { a, b, c, d }
let res = []
for(let key in obj) {
res = res.concat(Array.isArray(obj[key]) ? obj[key] : []);
}
console.log(res)

Repeat an array with multiple elements multiple times in JavaScript

In JavaScript, how can I repeat an array which contains multiple elements, in a concise manner?
In Ruby, you could do
irb(main):001:0> ["a", "b", "c"] * 3
=> ["a", "b", "c", "a", "b", "c", "a", "b", "c"]
I looked up the lodash library, and didn't find anything that was directly applicable. Feature request: repeat arrays. is a feature request for adding it to lodash, and the best workaround given there is
const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;
const repeatedArray = _.flatten(_.times(numberOfRepeats, _.constant(arrayToRepeat)));
The questions Most efficient way to create a zero filled JavaScript array? and Create an array with same element repeated multiple times focus on repeating just a single element multiple times, whereas I want to repeat an array which has multiple elements.
Using reasonably well-maintained libraries is acceptable.
No need for any library, you can use Array.from to create an array of arrays you want repeated, and then flatten using [].concat and spread:
const makeRepeated = (arr, repeats) =>
[].concat(...Array.from({ length: repeats }, () => arr));
console.log(makeRepeated([1, 2, 3], 2));
On newer browsers, you can use Array.prototype.flat instead of [].concat(...:
const makeRepeated = (arr, repeats) =>
Array.from({ length: repeats }, () => arr).flat();
console.log(makeRepeated([1, 2, 3], 2));
You can use the Array constructor along with its fill method to fill it a number of times of the array you want to repeat, then concat them (the subarrays) into a single array:
const repeatedArray = [].concat(...Array(num).fill(arr));
Note: On older browsers (pre-ES6), you can use Function#apply to mimic the rest syntax above (concat will be called with each of the sub arrays passed to it as argument):
var repeatedArray = [].concat.apply([], Array(num).fill(arr));
Example:
const arrayToRepeat = [1, 2, 3];
const numberOfRepeats = 3;
const repeatedArray = [].concat(...Array(numberOfRepeats).fill(arrayToRepeat));
console.log(repeatedArray);
const repeat = (a, n) => Array(n).fill(a).flat(1)
console.log( repeat([1, 2], 3) )
Recursive alternative:
const repeat = (a, n) => n ? a.concat(repeat(a, --n)) : [];
console.log( repeat([1, 2], 3) )
My first idea would be creating a function like this
let repeat = (array, numberOfTimes) => Array(numberOfTimes).fill(array).reduce((a, b) => [...a, ...b], [])
console.log(repeat(["a", "b", "c"], 3))
using the fill method and reduce
Ideally, instead of using reduce you could use flatten but there's yet no support in browsers
Try
Array(3).fill(["a", "b", "c"]).flat()
console.log( Array(3).fill(["a", "b", "c"]).flat() );
Unfortunately, it is not possible natively in JS (Also operator overloading is not possible, so we can not use something like Array.prototype.__mul__), but we can create an Array with the proper target length, fill with placeholders, then re-map the values:
const seqFill = (filler, multiplier) =>
Array(filler.length * multiplier)
.fill(1)
.map(
(_, i) => filler[i % filler.length]
);
console.log(seqFill([1,2,3], 3));
console.log(seqFill(['a','b','c', 'd'], 5));
Or another way by hooking into the Array prototype, you could use the syntax of Array#seqFill(multiplier), this is probably the closest you can get to ruby syntax (rb can do basically everything with operator overloading, but JS can't):
Object.defineProperty(Array.prototype, 'seqFill', {
enumerable: false,
value: function(multiplier) {
return Array(this.length * multiplier).fill(1).map((_, i) => this[i % this.length]);
}
});
console.log([1,2,3].seqFill(3));
Apart from the obvious [].concat + Array.from({length: 3}, …)/fill() solution, using generators will lead to elegant code:
function* concat(iterable) {
for (const x of iterable)
for (const y of x)
yield y;
}
function* repeat(n, x) {
while (n-- > 0)
yield x;
}
const repeatedArray = Array.from(concat(repeat(3, [1, 2, 3])));
You can also shorten it to
function* concatRepeat(n, x) {
while (n-- > 0)
yield* x;
}
const repeatedArray = Array.from(concatRepeat(3, [1, 2, 3]));
Though other methods works simply, these too.
Array.fill() and Array.from() in previous methods will not work in IE. MDN Docs for Reference
Mehtod 1 : Loop and push (Array.prototype.push) the same into the array.
function mutateArray(arr,n)
{
var temp = [];
while(n--) Array.prototype.push.apply(temp,arr);
return temp;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));
Method 2: Join the array elements and String.repeat() to mutate the string and return the split string.
Note: The repeat method is not supported yet in IE and Android webviews.
function mutateArray(arr,n)
{
var arr = (arr.join("$")+"$").repeat(n).split("$");
arr.pop(); //To remove the last empty element
return arr;
}
var a = [1,2,3,4,5];
console.log(mutateArray(a,3));

How do I get this 'Sorted Union' function to work using Array.concat, in javaScript

I am going through this exercise on FCC which requires the following:
Write a function that takes two or more arrays and returns a new array
of unique values in the order of the original provided arrays.
In other words, all values present from all arrays should be included
in their original order, but with no duplicates in the final array.
The unique numbers should be sorted by their original order, but the
final array should not be sorted in numerical order.
This is my code:
function uniteUnique(){
var elm, exists = {},
outArr = [],
arr = [],
args = Array.prototype.slice.call(arguments);
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
for(var i =0; i<arr.length; i++){
elm = arr[i];
if(!exists[elm]){
outArr.push(elm);
exists[elm] = true;
}
}
return arr;
}
My problem centers around this line.
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
I'd like all the arguments/arrays to go through the filter method and then get concatenated, any help would be appreciated!
Boolean will not filter unique items, it will simply return Boolean(arg) value which is not the intended one.
Replace
args.forEach(function(arg) {
arr.concat(arg.filter(Boolean));
});
with
args.forEach(function(arg) {
arr.concat(arg.filter(function(val){
return arr.indexOf(val) == -1;
}));
});
This will only concatenate array items which are unique
Well may be you prefer the following single liner functional approach instead;
var getUniques = (...a) => a.reduce((p,c)=> p.concat(c)).reduce((p,c) => {!~p.indexOf(c) && p.push(c); return p},[]);
document.write("<pre>" + getUniques([1,2,3],[3,4,5],[3,4,5,6,7,8],[0,1,2,3,4,5,6,7,8,9]) + "</pre>");
The getUniques function returns an array of all uniques in the order of appearance. Note that there is no arguments object in the arrow functions but the ...rest parameters of ES6 work just as well for that purpose. Even if you don't like the functional approach the logic behind may influence you to implement the same functionality with conventional functions and for loops.
And an even more simplified version of the above one is as follows
var getUniques = (...a) => a.reduce((p,c) => {c.forEach(e => !~p.indexOf(e) && p.push(e)); return p});
document.write("<pre>" + getUniques([1,2,3],[3,4,5],[3,4,5,6,7,8],[0,1,2,3,4,5,6,7,8,9]) + "</pre>");
function union(arrays) {
const u = arrays.reduce(function(acc, iVal) {
return acc.concat(iVal);
})
return [...new Set(u)];
}
var arr1 = [5, 10, 15];
var arr2 = [15, 88, 1, 5, 7];
var arr3 = [100, 15, 10, 1, 5];
console.log(union([arr1, arr2, arr3])); // should log: [5, 10, 15, 88, 1, 7, 100]

Categories