Reputation: 3131
I have seen many question/answer subject to merge two array by alternating Values. they are working like this:
let array1 = ["a", "b", "c", "d"];
let array2 = [1, 2];
let outcome = ["a",1 ,"b", 2, "c", "d"]
but i want output to be more efficient with even distribution of value based on array size.
expected outcome = ["a","b", 1, "c", "d", 2]
other scenario
let array2 = [1];
expected outcome = ["a","b", 1, "c", "d"]
what should be the best way to achieve this sort of merging?
Upvotes: 2
Views: 939
Reputation: 3355
This function was influenced by adiga's answer but handles the distribution a little better by calculating the insert index based on a decimal interval instead of Math.ceil
.
It also avoids mutating the input arrays by creating a copy of the long array before inserting the short array's data.
If you find any cases that it doesn't cover let me know :)
function mergeAndDistributeArrays(array1, array2) {
// Find the long/short arrays based on length
const [long, short] =
array1.length >= array2.length ? [array1, array2] : [array2, array1];
// Calculate the interval
const interval = long.length / (short.length + 1);
// Copy the long array so we don't mutate the input arrays
const merged = [...long];
// Iterate the short array and insert the values into the long array
short.forEach((value, index) => {
// Calculate the insert index based on the interval and the current index
const insertAt = Math.ceil(interval * (index + 1));
// Insert the value
merged.splice(insertAt + index, 0, value);
});
return merged;
}
console.log(
mergeAndDistributeArrays(
[1,2,3],
['a','b','c','d','e','f','g','h','i']
)
);
Upvotes: 2
Reputation: 1
const mix = (firstArray, secondArray) => {
const itrArray = firstArray.length > secondArray.length ? firstArray : secondArray;
const result = [];
for(let i=0; i<itrArray.length; i++){
firstArray[i] && result.push(firstArray[i]);
secondArray[i] && result.push(secondArray[i]);
}
return result;
}
console.log(mix([1, 2, 3], [4, 5, 6]));
// [1, 4, 2, 5, 3, 6]
console.log(mix(["h", "a", "c"], [7, 4, 17, 10, 48]));
// ["h", 7, "a", 4, "c", 17, 10, 48]
Upvotes: 0
Reputation: 159
let array1 = ['a', 'b', 'c', 'd', 'e'];
let array2 = [1, 2];
function merge(arr1, arr2) {
let newArr1 = JSON.parse(JSON.stringify(arr1));
let newArr2 = JSON.parse(JSON.stringify(arr2));
[newArr1, newArr2] = newArr1.length >= newArr2.length ? [newArr1, newArr2] : [newArr2, newArr1];
const interval = newArr1.length / newArr2.length;
newArr2.map((item, index) => {
newArr1.splice(interval * (index + 1), 0, item);
})
return newArr1;
}
console.log(merge(array1, array2));
Upvotes: 0
Reputation: 35253
You could get the interval for distribution. Then loop through the second array and use splice
to update the specific indices of the first array.
function distribute(original, replace) {
const interval = Math.ceil(original.length / (replace.length + 1));
replace.forEach((r, i) => original.splice(interval * (i + 1) + i, 0, r))
console.log(...original)
}
distribute(["a", "b", "c", "d"], [1])
distribute(["a", "b", "c", "d"], [1, 2])
distribute(["a", "b", "c", "d"], [1, 2, 3])
distribute(["a", "b", "c", "d", "e", "f"], [1, 2])
distribute(["a", "b", "c", "d", "e", "f"], [1, 2, 3])
Upvotes: 1
Reputation: 21638
Find the ratio of the two arrays' lengths, longest.length/shortest.length
and then take that many from the longest for every one in the shortest.
let array1 = ["a", "b", "c", "d", "e"];
let array2 = [1, 2];
const evenDistribute = (array1, array2) => {
const longest = array1.length > array2.length ? array1 : array2;
const shortest = array1.length > array2.length ? array2 : array1;
const ratio = Math.floor(longest.length / shortest.length);
const results = [];
for (let i = 0; i < shortest.length; i++) {
for (let j = 0; j < ratio; j++) {
results.push(longest[i * ratio + j]);
}
results.push(shortest[i]);
}
// Grab any that are left over
for (let i = longest.length - (longest.length % shortest.length); i < longest.length; i++) {
results.push(longest[i]);
}
return results;
}
console.log(evenDistribute(array1, array2));
Upvotes: 2
Reputation: 23818
The idea is to find out per how many items of the long array you will have to mix an item from the short array. The code below is to demonstrate the concept. Maybe you will have to adjust it a little bit for all edge scenarios.
let array1 = ["a", "b", "c", "d"];
let array2 = [1, 2];
//Get the long and short arrays and calc the length factor
var [longArray, shortArray] = array1.length >= array2.length ? [array1, array2] : [array2, array1];
let lengthFactor = longArray.length / shortArray.length;
var c = 0
let smallIdx = 0;
let result = longArray.flatMap(item => {
c++;
if (c % lengthFactor === 0) {
return [item, shortArray[smallIdx++]]
}
else
return [item];
})
console.log(result);
Upvotes: 1