Skip to content

Instantly share code, notes, and snippets.

@pentaphobe
Created November 13, 2013 17:53
Show Gist options
  • Save pentaphobe/7453370 to your computer and use it in GitHub Desktop.
Save pentaphobe/7453370 to your computer and use it in GitHub Desktop.
Iteratively merge arrays, preserving relative order
/**
* This seems like a problem which can be solved more elegantly, but I needed this code today
* so despite a strong urge to sit down with pen and paper and relive my Godel, Escher, Bach days
* I must instead move along for now.
*
*
*/
!function() {
/**
* Merge two arrays, maintaining order as much as possible
*/
function mergeArrays(left, right) {
var result = [],
leftItem, rightItem,
leftIdx, rightIdx;
/**
* Early out for invalid arguments
* doesn't check type
*/
if (!left || !right || (!left.length && !right.length)) {
return result;
}
/**
* Special case to iteratively reduce
*/
if (arguments.length > 2) {
right = mergeArrays.apply(this, Array.prototype.slice.call(arguments, 1));
}
// first add any data which precedes the first entry of left (ie. prepended to reference)
leftItem = left[0];
rightIdx = right.indexOf(leftItem);
if (rightIdx !== -1) {
result = result.concat( right.slice(0, rightIdx) );
right = right.slice(rightIdx);
}
// scan for matches
for (var i=0, max=left.length; i < max && right.length !== 0; i++) {
leftItem = left[i];
rightItem = right[0];
// same? simply insert
if (leftItem === rightItem) {
result.push(leftItem);
right = right.slice(1);
continue;
}
// otherwise, if it doesn't exist, simply add it
rightIdx = right.indexOf(leftItem);
if (rightIdx === -1) {
result.push(leftItem);
continue;
}
// otherwise inject whatever exists until that point, skipping
// anything which exists in the left
for (var j=0; j < rightIdx; j++) {
var rightItem = right[j];
var leftIdx = left.indexOf(rightItem);
if (leftIdx === -1) {
result.push(rightItem);
}
}
right = right.slice(rightIdx);
// at this stage we don't actually want to step forward on the left array
i--;
}
// finally add any appended data from right
result = result.concat( right );
return result;
}
var first = [
'hello',
'foghorn',
'does not exist in second',
'leghorn'
];
var second = [
'prepended',
'hello',
'inserted first',
'foghorn',
'inserted second',
'inserted more',
'leghorn',
'appended'
];
var third = [
'inserted first',
'chickens',
'inserted more',
'appended',
'extra',
'stuff'
];
var test = mergeArrays(first, second, third);
console.log(test);
}();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment