【问题标题】:Javascript mulilevel array sort based on key, but with logical structure in first key基于键的Javascript多级数组排序,但在第一个键中具有逻辑结构
【发布时间】:2020-12-22 13:39:09
【问题描述】:

我有一些具体的问题。我有很多这样的记录:

let a = [
  [[1,2,3], ... , b],
  [[1,2,5], ... , a]
  [[1,2], ... , a],
  [[1], ... , z]
  [[1,2,5], ... , a],
  [[1,2,3,5], ... , b],
  [[1,2,3,4], ... , a],
  [[1,3], ... , a],
  [[1,3,3], ... , b],
  [[1,6], ... , a],
  [[1,3,5], ... , d],
  [[1,2,4], ... , b],
  [[1,3,1], ... , a],
  [[1,3,2], ... , c],
]

所以我有数组(级别 0)和数组(级别 1),其中包含一些数据和路径部分的数组(级别 2)。

现在,我必须通过例如键 2 对数组级别 0 进行排序,但路径仍应构建逻辑树或类似的东西。

因此,如果我按例如最后一个键进行排序,我应该得到这样的结果:

let b = [
  [[1], ... , z],
  [[1,2], ... , a],
  [[1,2,5], ... , a]
  [[1,2,3], ... , b],
  [[1,2,3,4], ... , a],
  [[1,2,3,5], ... , b],
  [[1,2,4], ... , b],
  [[1,2,6], ... , d],
  [[1,3], ... , a],
  [[1,3,1], ... , a],
  [[1,3,3], ... , b],
  [[1,3,2], ... , c],
  [[1,3,5], ... , d],
  [[1,6], ... , a],
]

解决了!

我发现最好和最简单的解决方案来自 lodash 库。所以我可以先按第一列排序,然后按选定键排序——这样结构就变得合乎逻辑,排序的只是“文件夹内的文件”。

代码如下:

let a = [
  [[1,2,3], ... , b],
  [[1,2,5], ... , a]
  [[1,2], ... , a],
  [[1], ... , z]
  [[1,2,5], ... , a],
  [[1,2,3,5], ... , b],
  [[1,2,3,4], ... , a],
  [[1,3], ... , a],
  [[1,3,3], ... , b],
  [[1,6], ... , a],
  [[1,3,5], ... , d],
  [[1,2,4], ... , b],
  [[1,3,1], ... , a],
  [[1,3,2], ... , c],
]

function TreeStructure(arr, column, dir) {
  // Create array duplicate to avoid changes on base array
  let a = [...arr];
  // flip sort direction based on passed value
  // Magic of _Lodash - firstly, sort by the tree ignoring the last item of the tree path,
  // Then sort by the selected key
  a = _.sortBy(a, [
    function (item) {
  // first - sort by the first array, but with ignoring the last item
  // as I mentioned - it's representation of folder tree
  // so the last element is the file
      const value = item[0].length > 1 ? item[0].slice(0, item[0].length - 1).join("-") : item[0].length;
      return value;
    },
    function (item) {
  // Then, sort by the selected column
  // To prevent errors if some objects or arrays comes in the column I convert them to string
  // And to avoid specyfic JS sorting, I convert it to lowercase.
      const value = item[column].toString().toLowerCase();
      return dir === "asc" ? value : -value;
    },
  ]);

return a;
}

【问题讨论】:

    标签: javascript arrays sorting directory tree


    【解决方案1】:

    最短的方法是使用String#localeCompare 与通过分隔符连接的所需数组的选项和字符串。

    此方法尊重多于一位的值并自然排序。

    为了对不同的列进行排序,您可以为每个排序方法获取函数和一个对象,该对象具有列的键并返回一个函数作为排序回调。

    const
        sortPath = col => (a, b) => a[col].join('-').localeCompare(
            b[col].join('-'),
            undefined,
            { numeric: true, sensitivity: 'base' }
        ),
        sortAlpha = col => ((a, b) => a[col].localeCompare(b[col])),
        cols = { path: sortPath(0), title: sortAlpha(1) },
        array = [[[1, 2, 3], 'b'], [[1, 2, 5], 'a'], [[1, 2], 'a'], [[1], 'z'], [[1, 2, 5], 'a'], [[1, 2, 3, 5], 'b'], [[1, 2, 3, 4], 'a'], [[1, 3], 'a'], [[1, 3, 3], 'b'], [[1, 6], 'a'], [[1, 3, 5], 'd'], [[1, 2, 4], 'b'], [[1, 3, 1], 'a'], [[1, 3, 2], 'c']];
    
    array.sort(cols.path);
    array.forEach(a => console.log(JSON.stringify(a)));
    
    console.log('----------');
    
    array.sort(cols.title);
    array.forEach(a => console.log(JSON.stringify(a)));
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

    • 这几乎是完美的,但我必须能够选择我正在排序的键。例如,如果我的值表示:[[paths-array], 'title', 'size', 'status', 'content'],我需要选择以相同的方式排序,但按第二个或第三个键.
    猜你喜欢
    • 1970-01-01
    • 2019-05-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-15
    • 2016-06-28
    • 2016-09-20
    • 2013-09-26
    相关资源
    最近更新 更多