复杂的数组合并(保留顺序)

时间:2019-11-11 17:40:10

标签: javascript

我有两个数组,如下所示:

const array1 = [
  {
    id: 'a1',
    text: 'some text'
  },
  {
    id: 'a2',
    text: 'some more text',
  },
  {
    id: 'a3',
    text: 'some more text',
  },
]

const array2 = [
  {
    id: 'a1',
    text: 'some text' 
  },
  {
    id: 'ab12',
    text: 'some text' 
  },
  {
    id: 'abc123',
    text: 'some further text'
  },
  {
    id: 'a3',
    text: 'some more text' 
  },
  {
    id: 'bx44',
    text: 'some more text' 
  },
]

我想将这些数组与必须结合每个数组是否具有与其他数组一样的“ id”属性的信息结合在一起,所以:

combined = [
  {
    id: 'a1',
    text: 'some text',
    info: 'in-both'
  },
  {
    id: 'a2',
    text: 'some text',
    info: 'only-array1',
  },
  {
    id: 'ab12',
    text: 'some text',
    info: 'only-array2',
  },
  {
    id: 'abc123',
    text: 'some further text',
    info: 'only-array2',
  },
  {
    id: 'a3',
    text: 'some more text',
    info: 'in-both',
  },
  {
    id: 'bx44',
    text: 'some more text',
    info: 'only-array2',
  },
]

我正在尝试保持“固有”顺序,以便仅出现在array1或array2中的项相对于它们的索引在匹配项(两个数组中的项)之间结束。例如,“ a2”(仅存在于array1中)在“ a1”之后但在“ a3”之前。如果在匹配之间,只有在array1或array2中存在多个项目,则我要尝试使属于array1的项目优先出现(在示例中,“ a2”在“ ab12”和“ abc123”之前)

到目前为止的代码:

array1.reduce((all, curr, a1index, a1array) => {
  let correspondingItemInArray2Index = array2.findIndex(a2item => a2item.id === curr.id);
  if(correspondingItemInArray2Index === -1) {
    curr.info = 'only-in-array1';
  }
  else if(correspondingItemInArray2Index === a1index) {
    // Items are on same level...
    curr.info = 'in-both';
  }
  else {
    ... // I need to find all items of array2 until the next 'match' of ids?
  }

}
, []);

1 个答案:

答案 0 :(得分:2)

您可以获取常见项目并在所有项目之间进行迭代。

function merge(...data) {
    var common = data.map(a => a.map(({ id }) => id)).reduce((a, b) => a.filter(v => b.includes(v))),
        indices = data.map(_ => 0),
        result = [];

    while (indices.every((l, i) => l < data[i].length)) {
        indices = indices.map((j, i) => {
            while (j < data[i].length && !common.includes(data[i][j].id)) {
                result.push(Object.assign({}, data[i][j++], { info: ['a', 'b'][i] }));
            }
            return j;
        });
        if (indices.some((l, i) => l >= data[i].length)) break;
        result.push(Object.assign({}, data[0][indices[0]], { info: 'both' }));
        indices = indices.map(v => v + 1);
    }
    indices.forEach((j, i) => {
        while (j < data[i].length) {
            result.push(Object.assign({}, data[i][j++], { info: ['a', 'b'][i] }));
        }
    });
    return result;
}


var array1 = [{ id: 'a1', text: 'some text' }, { id: 'a2', text: 'some more text' }, { id: 'a3', text: 'some more text' }],
    array2 = [{ id: 'a1', text: 'some text' }, { id: 'ab12', text: 'some text' }, { id: 'abc123', text: 'some further text' }, { id: 'a3', text: 'some more text' }, { id: 'bx44', text: 'some more text' }],
    result = merge(array1, array2);

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }