Javascript:对齐并行数组索引避免重叠

标签 javascript arrays sorting

我有一个数组列表,其中相同的项目可能出现在不同的列表中(但不在同一个列表中)。
我正在尝试对数组进行排序,以便匹配项在所有数组中具有相同的索引。
我也在尝试尽可能填补空白,但如果某些位置仍未定义,那也没关系。
条件

  • 所有的重复都是连续的,所以如果一个元素是重复的,那么前一个数组中肯定有一个副本。
  • 每个数组中的每一项只能出现一次(重复对象仅在不同的数组中)
  • foo 数组可能有不同的长度
  • foo 数组总是存在的,在最坏的情况下它是空的。
  • 只要目标完成, foo 数组中的顺序就无关紧要了。
  • 包装器数组无法排序。

  • 输入
    const myWrapper [
        { foo: [] },
        { foo: ['A', 'B', 'C', 'D'] },
        { foo: ['X', 'A', 'E', 'C'] },
        { foo: ['X', 'F', 'C', 'G', 'H'] },
        { foo: ['C'] }
    ];
    
    所需输出
    const myWrapper [
        { foo: [] },
        { foo: ['B', 'A', 'C', 'D'] },
        { foo: ['X', 'A', 'C', 'E'] },
        { foo: ['X', 'F', 'C', 'G', 'H'] },
        { foo: [undefined, undefined, 'C'] }
    ];
    
    有没有一种巧妙的方法来实现这一目标?
    我的尝试,从右侧排序并使用 tmp 变量来交换项目。
    这似乎效果不佳,因为以下位置有时会移动先前的项目,从而弄乱先前迭代中设置的顺序。
        let tmp;
        myWrapper.forEach((item, wrapperIndex) => {
            item.foo.forEach((currentFoo, fooIndex) => {
                 // Search for match in the previous foo
                 if(myWrapper[wrapperIndex - 1]) {
                    const prevFoo = myWrapper[wrapperIndex - 1].foo;
                    const prevIndex = prevFoo.indexOf(item);
                    if (prevIndex >= 0 && prevIndex !== fooIndex) {
                        tmp = prevFoo[fooIndex];
                        prevFoo[fooIndex] = prevEvents[prevIndex];
                        prevFoo[prevIndex] = tmp;
                    }
                }
            });
        });
    
    编辑:问题还在于循环对单个项目(实际上是对象,我使用字符串来简化)执行其他操作,所以我不能从右侧移动(当前项目)。

    The output is rendered via Angular using 2 nested *ngFor so the final result has to maintain this array structure.

    最佳答案

    编辑
    一个更简单的解决方案,使用与我原始答案相同的重复映射,然后使用简单的交换算法将重复值移动到相应的索引中。

    const myWrapper = [
      { foo: [] },
      { foo: ['A', 'B', 'C', 'D'] },
      { foo: ['X', 'A', 'E', 'C'] },
      { foo: ['X', 'F', 'C', 'G', 'H'] },
      { foo: ['C'] }
    ];
    
    // find dupes and create map of indexes
    let
      seen = new Set,
      dupeMap = {}, d = 0;
    for (const { foo } of myWrapper) {
      for (const x of foo) {
        seen.has(x)
          ? dupeMap[x] ??= d++
          : seen.add(x);
      }
    }
    
    // swap duplicates into appropriate indexes
    for (const { foo } of myWrapper) {
      let
        i, j, temp;
      for (i = 0; i < foo.length; i++) {
        j = dupeMap[foo[i]];
        if (j !== undefined && j !== i) {
          temp = foo[i];
          foo[i] = foo[j];
          foo[j] = temp;
          i--;
        }
      }
    }
    
    myWrapper.forEach(({ foo }) => console.log(`{foo: [${foo.map(e => e ?? ' ').join(', ')}]}`));
    .as-console-wrapper { max-height: 100% !important; top: 0; }


    原答案
    这是一个避免排序的相当简单的解决方案。它首先创建一个对象,其中包含重复值的 Prop 和最终数组中该值的预期索引作为值。
    然后它遍历每个 foo数组通过重复映射中的索引将重复值放置在临时数组中,并将唯一值推送到第二个临时数组。
    在退出之前,它会尝试从唯一数组中的任何值回填临时重复数组中的漏洞。
    这会改变 myWrapper阵列到位。

    const myWrapper = [
      { foo: [] },
      { foo: ['A', 'B', 'C', 'D'] },
      { foo: ['X', 'A', 'E', 'C'] },
      { foo: ['X', 'F', 'C', 'G', 'H'] },
      { foo: ['C'] }
    ];
    
    // find dupes and create map of indexes
    let
      seen = new Set,
      dupeMap = {}, d = 0;
    for (const { foo } of myWrapper) {
      for (const x of foo) {
        seen.has(x)
          ? dupeMap[x] ??= d++
          : seen.add(x);
      }
    }
    
    for (const obj of myWrapper) {
      // collect elements into dupe/unique temp arrays
      const
        { foo } = obj,
        dTemp = [], uTemp = [];
      for (const e of foo) {
        (e in dupeMap)
          ? dTemp[dupeMap[e]] = e
          : uTemp.push(e);
      }
    
      // backfill empty indexes in dupe temp array
      for (const [i, d] of dTemp.entries()) {
        if (d === undefined && uTemp.length) {
          dTemp.splice(i, 1, uTemp.shift());
        }
      }
    
      // concat back into foo
      obj.foo = [...dTemp, ...uTemp];
    }
    
    myWrapper.forEach(({ foo }) => console.log(`{foo: [${foo.map(e => e ?? ' ').join(', ')}]}`));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    关于Javascript:对齐并行数组索引避免重叠,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67583456/

    相关文章:

    javascript - 如何在odoo中实现recaptcha

    ios - 为什么我的图像没有附加到数组中?

    c++ - 为什么 C++ Lambda 函数作为比较函数比等效对象快得多

    list - lisp 通过函数排序列表

    java - 对已排序的列表进行排序时,列表迭代在 Java 8 中抛出 ConcurrentModificationException

    c# - 从 C# 代码后面传递函数参数

    javascript - 我的休假申请表中的回形针选项用于附加文件

    Java 二维数组逻辑实现

    c - 如何将 char[n][length+1] 转换为 C 中的常量字符串数组?

    javascript - 在链接上悬停操作后图像叠加悬停失败