【问题标题】:How does one, for nested arrays, rearrange the order in a way that the last string item of an array equals the first string item of the following one?对于嵌套数组,如何重新排列顺序,使数组的最后一个字符串项等于下一个字符串的第一个字符串项?
【发布时间】:2020-12-29 22:02:25
【问题描述】:

我需要达到这个结果

[['peanuts', 'butter'], ['butter', 'jelly'], ['jelly', 'bananas'], ['bananas', 'apples']]

来自这个数组

[['butter', 'jelly'], ['bananas', 'apples'], ['peanuts', 'butter'], ['jelly', 'bananas']]

我希望每个数组的第二个元素与下一个数组的第一个元素匹配。

我认为排序函数是这里最好的选择,但是我已经尝试过了,但这不起作用(实际上可以,但不是所有数组都可以)

.sort(([a, b], [c, d]) => {
    return b === c ? -1 : 1
})

【问题讨论】:

  • 你的排序标准是什么?
  • @iota 数组的每个下一个 [0] el 应该是前一个数组的 [1] el。像 [['a', 'b'], ['b', c'], ['c', 'd'], ['d', 'e'] 等
  • @MariaCornetti ...还有什么问题吗?
  • @PeterSeliger 不,谢谢!
  • @PeterSeliger 你说得对,对不起,忘记了

标签: javascript arrays algorithm sorting


【解决方案1】:

排序不是解决这个问题的最佳方法。相反,您可以为第一个和第二个元素创建查找表并按顺序浏览它们。

const arr = [
  ['butter', 'jelly'],
  ['bananas', 'apples'],
  ['peanuts', 'butter'],
  ['jelly', 'bananas']
];
const lookupFirst = {},
  lookupSecond = {};
for (let i = 0; i < arr.length; i++) {
  lookupFirst[arr[i][0]] = i;
  lookupSecond[arr[i][1]] = i;
}
const next = arr.map(x => lookupFirst[x[1]]);
let curr = arr.findIndex(x => !lookupSecond[x[0]]);
const res = [];
do {
  res.push(arr[curr]);
} while ((curr = next[curr]) !== undefined);
console.log(JSON.stringify(res));

【讨论】:

    【解决方案2】:

    排序将无济于事,而是需要一种算法,例如,首先搜索没有任何匹配项的唯一数组,该匹配项将其链接到任何其他数组。

    这个数组的第一项(一个字符串)然后是这个数组的链接,前一个数组的最后一项与前面提到的第一项匹配。

    上述过程splices 从输入值中每个匹配的数组并将它们收集(unshift)到一个结果数组中,因此它改变了输入值,因此只需要继续直到输入值得到清空。

    function getCopyInDominoesLikeOrder(list) {
      // in order to not directly mutate the input value.
      list = Array.from(list);
    
      // get the array where its last item does not match
      // any other array's first item, which makes it the
      // last array of the return value.
      let itemListIndex = list.findIndex(aList =>
        list.every(bList => aList[aList.length - 1] !== bList[0])
      );
      let itemList = list.splice(itemListIndex, 1)[0];
    
      const result = [itemList]; // return value.
      let firstItem = itemList[0];
    
      // mutate/reduce the input value's copy while looking
      // for the array where its last item matches the first
      // item of the previously found/extracted (linked) array.
      while (list.length !== 0) {
    
        itemListIndex = list.findIndex(aList =>
          aList[aList.length - 1] === firstItem 
        );
        itemList = list.splice(itemListIndex, 1)[0]; // mutate/reduce.
        result.unshift(itemList); // aggregate return value.
    
        firstItem = itemList[0];
      }
      return result;
    }
    
    const arr = [
      ['butter', 'jelly'],
      ['bananas', 'apples'],
      ['peanuts', 'butter'],
      ['jelly', 'bananas'],
    ];
    console.log(
      'original :: arr :',
      arr
    );
    console.log(
      'sorted :: getCopyInDominoesLikeOrder(arr) :',
      getCopyInDominoesLikeOrder(arr)
    );
    .as-console-wrapper { min-height: 100%!important; top: 0; }

    【讨论】:

      【解决方案3】:

      看起来你只需要在排序回调中从每个数组中提取第一个元素,然后返回字典差异:

      const arr = [['c','d'], ['a','b'], ['d','e'], ['b','c']];
      
      arr.sort((a, b) => a[0].localeCompare(b[0]));
      console.log(arr);

      【讨论】:

      • 很抱歉,第一个示例对我的真实案例没有提供信息。请检查更新的问题。对于 ['a', 'b'] 情况,您的答案非常有效!
      【解决方案4】:
      .sort(([a], [b]) => a > b)
      

      【讨论】:

      • '>' 运算符不适合这种情况。我更新了我的问题
      猜你喜欢
      • 1970-01-01
      • 2020-07-02
      • 1970-01-01
      • 2016-10-07
      • 1970-01-01
      • 1970-01-01
      • 2019-08-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多