如何叠加数组

时间:2017-08-17 09:05:38

标签: javascript

我需要这样的功能:

function imbricate(...arrays){}

返回一个新数组。

imbricate(["a","c","d"],["b","c"],["z","a"],["b","y","d"],["e","f","g"])

应返回:z,a,b,y,c,d,e,f,g,因为:

  • a,b,c,d(第一次通过)const r1=imbricate(["a","c","d"],["b","c"])
  • z,a,b,c,d(第二遍)const r2=imbricate(r1,["z","a"])
  • Z,A,B,Y,C,d
  • Z,A,B,Y,C,d,E,F,G

2 个答案:

答案 0 :(得分:1)

您可以尝试以下逻辑:

  • 创建一个虚拟数组,并用第一个数组的值填充它。
  • 现在循环其余参数并检查当前参数是否为数组。如果没有,以下解决方案将忽略它。
  • 现在为previousIndex(解决方案中pIndex)创建一个变量,该变量将保存先前匹配的索引的位置
  • 如果是Array,以递减的方式循环它并检查当前元素是否存在并将其索引保存在另一个变量中,例如index
    • 如果index大于-1,则表示数组中存在值,我们无需推送它。
    • 现在,如果pIndex-1index-1,则为新项目,我们可以在最后推送它。使用新职位更新pIndex
    • 如果pIndex不是-1,请将当前元素推到此位置并移动其余元素。



function imbricate(){
  var args = arguments;
  var result = [].concat(args[0]);
  for(var i = 1; i< args.length; i++){
    if(!Array.isArray(args[i])) continue;
    var pIndex = -1;
    args[i].reduceRight(function(p,c){
      var index = p.indexOf(c);
      if(index < 0){
        if(pIndex >= 0){
          p.splice(pIndex, 0, c);
          index = pIndex;
        }
        else{
          p.push(c);
          index = p.length - 1;
        }
      }
        
      pIndex = index;
      return p;
    }, result)
  }
  return result;
}

var r = imbricate(["a","c","d"],["b","c"],["z","a"],["b","y","d"],["e","f","g"]);

console.log(r)
&#13;
&#13;
&#13;

注意:考虑到评论中@ Nina指出的歧义,可以将此答案作为参考。以上答案将优先级视为先到先得顺序。因此,如果您有[a,c], [b, c], [d, c],则输出为[a, b, d, c]

答案 1 :(得分:0)

最后,

我做了一个班轮:-)来解决我的问题:

function imbricate(...arrays) {
function split(refArray, array = []) {
    if (!refArray.some(v => array.indexOf(v) > -1)) return [array];
    let returnArray = [];
    let previousIndex = 0;
    for (const v of refArray) {
        if (array.indexOf(v) > -1) {
            returnArray.push(array.slice(previousIndex, array.indexOf(v) + 1));
            previousIndex = array.indexOf(v);
        }
    }
    if (previousIndex != array.length - 1) returnArray.push(array.slice(previousIndex));
    return returnArray;
}
function merge(refArray = [], array = []) {
    let rangeMinIndex = array.findIndex(v => refArray.indexOf(v) > -1);
    let rangeMaxIndex = array.slice(rangeMinIndex + 1).findIndex(v => refArray.indexOf(v) > -1);
    if (rangeMinIndex == rangeMaxIndex && rangeMinIndex < 0) return [...refArray, ...array];
    if (rangeMaxIndex < 0) rangeMaxIndex = array.length - 1;
    if (rangeMinIndex == rangeMaxIndex && rangeMinIndex == 0) return [...refArray];
    if (rangeMinIndex == rangeMaxIndex)
        return [
            ...refArray.slice(0, refArray.indexOf(array[rangeMinIndex])),
            ...array.slice(0, rangeMaxIndex),
            ...refArray.slice(refArray.indexOf(array[rangeMinIndex]))
        ];

    if (
        array.slice(rangeMinIndex + 1).findIndex(v => refArray.indexOf(v) > -1) == -1 &&
        rangeMaxIndex == array.length - 1
    )
        return [
            ...refArray.slice(0, refArray.indexOf(array[rangeMinIndex]) + 1),
            ...array.slice(rangeMinIndex + 1), //, rangeMaxIndex+1),
            ...refArray.slice(refArray.indexOf(array[rangeMinIndex]) + 1)
        ];
    return [
        ...refArray.slice(0, refArray.indexOf(array[rangeMinIndex]) + 1),
        ...array.slice(rangeMinIndex + 1, rangeMaxIndex + 1),
        ...refArray.slice(refArray.indexOf(array[rangeMinIndex]) + 1)
    ];
}
let current;
for (const array of arrays) {
    if (!current) current = [...array];
    else {
        for (const splitted of split(current, array)) current = merge(current, splitted);
    }
}
return current;

}

第一个数组始终是引用,它将其他数组拆分为仅包含基于引用数组中包含的值的边界的块,然后根据边界定位进行合并。

无论如何,谢谢你的帮助。