interleave mutliple arrays in javascript - javascript

We have an Array of arrays, which we want to interleave into a single array:
i.e:
masterArray = [[1, 2, 3], ['c', 'd', 'e']] => [1, 'c', 2, 'd', 3, 'e'],
if arrays are not of equal length, pad it to the longest innerArray's length.
i.e
[1, 2, 3], [4, 5]) => [1, 4, 2, 5, 3, null]
I've satisfied this condition with the case of 2 arrays, however if the case is more than that. I struggle to form a strategy on dealing with more than 2.
[1, 2, 3], [4, 5, 6], [7, 8, 9] => [1, 4, 7, 2, 5, 8, 3, 6, 9]
function interleave(...masterArray) {
let rtnArray = [];
let longestArrayPosition = getLongestArray(masterArray);
let longestInnerArrayLength = masterArray[longestArrayPosition].length;
padAllArraysToSameLength(masterArray, longestInnerArrayLength); //pad uneven length arrays
masterArray[0].forEach((firstArrayNum, index) => {
const secondArrayNum = masterArray[1][index];
rtnArray.push(firstArrayNum);
rtnArray.push(secondArrayNum);
});
return rtnArray;
}
function getLongestArray(masterArray) {
return masterArray
.map(a=>a.length)
.indexOf(Math.max(...masterArray.map(a=>a.length)));
}
function padAllArraysToSameLength(masterArray, maxLength) {
return masterArray.forEach(arr => {
if (arr != maxLength) {
while(arr.length != maxLength) {
arr.push(null);
}
}
})
}

Use Array.from() to transpose the array of arrays (rows => columns and vice versa), and fill in the missing places with null. Flatten the tramsposed arrays of arrays with Array.flat():
const fn = arr => Array.from({
length: Math.max(...arr.map(o => o.length)), // find the maximum length
},
(_, i) => arr.map(r => r[i] ?? null) // create a new row from all items in same column or substitute with null
).flat() // flatten the results
const arr = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
const result = fn(arr)
console.log(result)

You can do this for any number of arrays with two nested forEach statements:
let arr1 = [[1,2,3],[4,5]]
let arr2 = [[1,2,3], [4,5,6], [7,8,9]]
let arr3 = [[1,2,3,4], [4,5,6], [7,8,9], [10,11,12]]
function interLeaveArrays(mainArr){
let maxLen = Math.max(...mainArr.map(arr => arr.length))
mainArr.forEach(arr => {
let lenDiff = maxLen - arr.length
for(let i=lenDiff; i>0; i--){
arr.push(null)
}
})
let newArr = []
mainArr.forEach((arr, idx1) => {
arr.forEach((el, idx2) => {
newArr[idx2 * mainArr.length + idx1] = el
})
})
return newArr
}
console.log(interLeaveArrays(arr1))
console.log(interLeaveArrays(arr2))
console.log(interLeaveArrays(arr3))

Related

How to remove '-' from the array number elements run through this function in JS?

I'm using this function below to sum "columns" of a 2D Array, but some elements contain '-' and I haven't been able to handle it:
I've tried Number(num) or typeof num === 'number', but still...
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const sumArray = (array) => {
const newArray = [];
array.forEach(sub => {
sub.forEach((num, index) => {
if(newArray[index]){
newArray[index] += num;
}else{
newArray[index] = num;
}
});
});
return newArray;
}
console.log(sumArray(arr))
You could use map and reduce to achieve this as well.
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1],
];
const sums = arr.map((sub) =>
sub.reduce((previous, current) => {
// check here that the value is a number
if (typeof current === 'number') {
return previous + current;
}
return previous;
}, 0)
);
console.log(sums);
// returns [23, 59, 9, 20]
Try:
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const sumArray = (array) => {
const newArray = [];
array.forEach(sub => {
sub.forEach((num, index) => {
if (typeof num == 'number') {
if (newArray[index]) {
newArray[index] += num;
} else {
newArray[index] = num;
}
}
});
});
return newArray;
}
console.log(sumArray(arr))
Here's a more concise solution:
const arr = [
['-', 2, 21],
[1, '-', 4, 54],
[5, 2, 2],
[11, 5, 3, 1]
];
const result = arr.map((e, i) => arr.reduce((a, c) => (typeof c[i] == 'number' ? a + c[i] : a), 0))
console.log(result)
Using splice() would help remove the - from the array

How can I insert each of an arrays elements every other element in another array? [duplicate]

This question already has answers here:
Merge two arrays with alternating values
(14 answers)
Merge Two Arrays so that the Values Alternate
(6 answers)
interleave mutliple arrays in javascript
(2 answers)
Closed 1 year ago.
I have two arrays.
let a = [1, 3, 5, 7]
let b = [2, 4, 6, 8]
I want the result:
a = [1, 2, 3, 4, 5, 6, 7, 8]
How can I insert each of array B's elements every other element in array A?
I have tried using splice in a for loop, but the length of array A changes so I cannot get it to work.
You can create a new array, loop through a and push the current item and the item in b at the same index:
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8];
let res = []
a.forEach((e,i) => res.push(e, b[i]))
console.log(res)
Alternatively, you can use Array.map and Array.flat:
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8];
let res = a.map((e,i) => [e, b[i]]).flat()
console.log(res)
If the arrays have the same length, then you can use flat map to avoid mutating the original array.
const a = [1, 3, 5, 7];
const b = [2, 4, 6, 8];
const res = b.flatMap((elem, index) => [a[index], elem]);
console.log(res);
You can try:
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8]
let newArray = [...a, ...b]
console.log(newArray) // [1, 3, 5, 7, 2, 4, 6, 8]
If you want to sort just
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8]
let newArray = [...a, ...b].sort((a, b) => a - b)
console.log(newArray) // [1, 2, 3, 4, 5, 6, 7, 8]
Create a new array and flatten it by doing the below.
let a = [1, 3, 5, 7]
let b = [2, 4, 6, 8]
console.log(a.map((e, i)=> [e, b[i]]).flat());
You could transpose the data and get a flat array.
const
transpose = (a, b) => b.map((v, i) => [...(a[i] || []), v]),
a = [1, 3, 5, 7],
b = [2, 4, 6, 8],
result = [a, b]
.reduce(transpose, [])
.flat();
console.log(result);
Don't splice, just create a new array and push them in on every other index.
Do a for loop, and on each loop do
newArrary.push(a[i]);
newArrary.push(b[i]);
You can use reduce
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8];
let c = a.reduce((acc, x, i) => acc.concat([x, b[i]]), []);
console.log(c)
This works for arrays of any length, adapt the code based on the desired result for arrays that are not the same length.
Using forEach and pushing the current element and the relative element from the other array is an option
let a = [1, 3, 5, 7];
let b = [2, 4, 6, 8];
let c = [];
a.forEach((x, i) => {c.push(x, b[i])});
console.log(c);
More about forEach - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

Delete all equal items from array

I have the next situation in my react application:
I have a state:
const [arr1, setArr1] = useState([1, 2, 3, 5, 1, 3]);
Bellow i render all items from array on UI like:
arr1.map(i => <li>{i}</li>)
Now i want to remove all items that are equal in the array:
ex:
[1, 2, 3, 5, 1, 3] // should be deleted 1 and 3 result: [1, 2, 5]
[1, 2, 3, 5, 3] // should be deleted 3 result: [1, 2, 5]
Deleting all items also the state should change here arr1.map().
I tried setArr1([new Set(arr1)]), but it does not delete all duplicated values, it delete just one of them.
How to achieve what i described above?
You can count the frequency of number and then just pick the number whose frequency is 1.
const arr = [1, 2, 3, 5, 1, 3],
frequency = arr.reduce((o,v) => (o[v] = (o[v] || 0) + 1, o), {}),
unique = Object.keys(frequency).reduce((r,k) => frequency[k] === 1? [...r, +k]: r, []);
console.log(unique);
Check if the the first index equal to the last index on an element,when they are equals it means it is unique:
let result = []
let arr = [1, 2, 3, 5, 1, 3]
arr.forEach(e => arr.indexOf(e) === arr.lastIndexOf(e)?result.push(e):null)
console.log(result)
You can calculate the frequency and remove the number if the frequency is greater than 1. codesandbox
function removeDuplicates(arr) {
const frequency = {};
arr.forEach((el) => {
frequency[el] = frequency[el] ? ++frequency[el] : 1;
});
const result = [];
for (el in frequency) {
if (frequency[el] === 1) {
result.push(el);
}
}
return result;
}
const arrayWithoutDuplicates = removeDuplicates(arr1);
return (
<ul>
{arrayWithoutDuplicates.map((el) => {
return <li key={el}> {el} </li>;
})}
</ul>
);
Below is a one-liner using filter
const arr = [1, 2, 3, 5, 1, 3];
const unique = arr.filter(x => arr.filter(y => y === x).length < 2)
console.log(unique);

How to remove one subset from an array in JS?

Let's say I have an array such as: [1, 1, 2, 2, 3, 3, 4, 5]
And I want to remove this array of elements [1, 2, 3, 4, 5]
So in the end I want to be left with [1, 2, 3]
I have tried using the method below but it removes all copies of the elements from the main array.
myArray = myArray.filter( function( el ) {
return !toRemove.includes( el );
} );
Here is a way to do it using filter, indexOf and splice.
const input = [1, 1, 2, 2, 3, 3, 4, 5];
function removeSubset(arr, subset) {
const exclude = [...subset];
return arr.filter(x => {
const idx = exclude.indexOf(x);
if (idx >= 0) {
exclude.splice(idx, 1);
return false;
}
return true;
});
}
console.log(removeSubset(input, [1, 2, 3, 4, 5]));
You could get a Map and count the values and filter by checking the count and decrement the count if found.
var array = [1, 1, 2, 2, 3, 3, 4, 5],
remove = [1, 2, 3, 4, 5],
map = remove.reduce((m, v) => m.set(v, (m.get(v) || 0) + 1), new Map),
result = array.filter(v => !map.get(v) || !map.set(v, map.get(v) - 1));
console.log(result);
One solution is looping on the array of elements to remove and for each one remove the first element found on the input array:
const input = [1, 1, 2, 2, 3, 3, 4, 5];
const removeItems = (input, items) =>
{
// Make a copy, to not mutate the input.
let clonedInput = input.slice();
// Search and remove items.
items.forEach(x =>
{
let i = clonedInput.findIndex(y => y === x);
if (i >= 0) clonedInput.splice(i, 1);
});
return clonedInput;
}
console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));
If you still want to use filter, you can use the items to remove as the this argument of the filter, something like this:
const input = [1, 1, 2, 2, 3, 3, 4, 5];
const removeItems = (input, items) =>
{
return input.filter(function(x)
{
let i = this.findIndex(y => y === x);
return i >= 0 ? (this.splice(i, 1), false) : true;
}, items.slice());
}
console.log(removeItems(input, [1,2,3,4,5]));
console.log(removeItems(input, [1,2]));
console.log(removeItems(input, [1,99,44,5]));
You can use Filter and Shitf and Sort
let arr = [1, 1, 2, 2, 3, 3, 4, 5]
let remove = [1, 3, 2, 4, 5].sort((a,b)=>a-b)
let op = arr.sort((a,b)=>a-b).filter(e => ( remove.includes(e) ? (remove.shift(), false) : true ))
console.log(op)

Iterate an array of arrays for a match from another array

I have an array of arrays, and I would like to iterate this array with the values of another array looking for a match.
let arr1 = [[1,3,5],[2,4,7],[1,5,9]] // [false, false, true]
let arr2 = [1,2,4,5,9] // arr2 contains all values of arr1[2]. return true.
I need it to return truthy falsey if all values in an arr1[i] are present in arr2
for (let i = 0; i < arr1.length; i++) {
if (arr2.every(arr1[i])) {
return true
}
}
You can use .map() with .every()
let arr1 = [[1,3,5],[2,4,7],[1,5,9]];
let arr2 = [1,2,4,5,9];
let result = arr1.map(x => x.every(y => arr2.includes(y)));
console.log(result);
or .filter() if you just want to get matching results:
let arr1 = [[1,3,5],[2,4,7],[1,5,9]];
let arr2 = [1,2,4,5,9];
let result = arr1.filter(x => x.every(y => arr2.includes(y)));
console.log(result);
You could use Array#some for a single boolean value by using Array#every for each inner array and check array2 with Array#includes.
var array1 = [[1, 3, 5], [2, 4, 7], [1, 5, 9]],
array2 = [1, 2, 4, 5, 9],
result = array1.some(a => a.every(v => array2.includes(v)));
console.log(result);
Using a Set.
var array1 = [[1, 3, 5], [2, 4, 7], [1, 5, 9]],
array2 = [1, 2, 4, 5, 9],
result = array1.some((s => a => a.every(v => s.has(v)))(new Set(array2)));
console.log(result);

Categories

Resources