【问题标题】:How can I sort an indirect array with javascript?如何使用 javascript 对间接数组进行排序?
【发布时间】:2020-07-17 18:19:48
【问题描述】:

在我的项目中,我需要对包含另一个数组(它是项)的索引的数组进行排序。我已经搜索了好几个小时,但没有找到遇到我问题的人。

var arr = [1, 4, 3, 4, 5, 6, 7, 8, 9];
function sorting(){
    let arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8];
    //sorting code
}

现在,我想对 arr2 进行排序,所以当我用这种代码循环遍历它时(在本段中),我使用排序数组 (arr2) 中的索引访问 arr。

  arr[arr2[i]]

我的第一步是使用 arr2.sort(function(a,b){arr[a] - arr[b]},但每次排序都不好。我尝试制作自己的排序函数,但我的问题仍然存在。

总而言之,我想对 arr2 进行排序,所以当我循环遍历它时,我会按升序(或降序)顺序获得 arr 的值。

编辑我解决了这个问题,但是当我在我的 html 上应用 arr2 时,出现了另一个问题。

    var arr = [1, 4, 3, 4, 5, 6, 7, 8, 9];
    function sorting(){
        let arr2 = [0, 1, 2, 3, 4, 5, 6, 7, 8];
        //The sorting block code (done)
        z = document.getElementsByClassName("triable"); //this is on what I applied arr2
        for (let i = 0; i < z.length; i++){
            z[i].style.order = arr2[i]; //this line work, but doesn't correctly do what I what it to do
        }
    }

对于 html,我有一些带有“可试用”类的 div,上面的代码需要应用 css 样式(顺序),以便 div 在视觉上改变位置

【问题讨论】:

  • 输出应该是什么样子的?
  • 在升序排序中,一切都很好,但在降序排序中,它给了我这个: [9, 6, 8, 7, 5, 4, 3, 4, 1] 当它应该给我:[9, 8, 7, 6, 5, 4, 4, 3, 1]
  • 请添加完整代码。否则你的数据不清楚。
  • Nina Scholz,这里是“完整代码”(我把你的部分代码放在排序块代码中)

标签: javascript html css arrays sorting


【解决方案1】:

您需要返回增量。否则回调会为每个调用返回undefined

arr2.sort(function(a, b) {
    return arr[b] - arr[a];
});

为了添加正确的顺序,您不需要从indices 中获取索引来寻址正确的元素并将i 指定为样式顺序值。

function sort() {
    var array = [1, 4, 3, 4, 5, 6, 7, 8, 9],
        z = document.getElementsByClassName("triable");

    [...array.keys()]
        .sort((a, b) => array[b] - array[a])
        .forEach((v, i) => z[v].style.order = i);
}
<button onclick="sort()">sort</button><br>
<div style="display: flex;">
<span class="triable">1</span>
<span class="triable">4</span>
<span class="triable">3</span>
<span class="triable">4</span>
<span class="triable">5</span>
<span class="triable">6</span>
<span class="triable">7</span>
<span class="triable">8</span>
<span class="triable">9</span> 
</div>

【讨论】:

  • 我的实际数组有更多的数字,但代码是一样的。当我尝试这样做时: arr2.sort(function(a, b) { return arr[b] - arr[a]; });对于降序数组,当我通过 arr2 访问 arr 时,这给了我这个序列:9、6、8、7、5、4、3、4、1,我的初始 arr 是:1、4、3、4、5、6 , 7, 8, 9
  • 我没有得到相同的结果。请参阅上文。
  • 您的代码非常适合升序排序,但它不适用于降序排序(这是我想把我的电脑放在窗口中的地方)
  • 只需交换ab
  • @NinaScholz 不错的解决方案??
【解决方案2】:

函数式任意排序

这是解决问题的另一种方法。假设我们有一些 fruits 和一个任意的 order 我们希望将它们排序 -

const fruits =
  //   0        1          2        3         4 
  [ "apple", "banana", "cherry", "orange", "peach" ]
  

const order =
  [ 1, 3, 2, 0, 4 ]

我们希望能够写出这样的东西-

fruits.sort(sortByIndex(fruits, order))

console.log(fruits)
// [ "banana", "orange", "cherry", "apple", "peach" ]
//      1         3         2         0        4

我们希望有一个 Comparison 模块来处理我们的排序代码 -

const { empty, map } =
  Comparison
  
const sortByIndex = (values = [], indexes = []) =>
  map(empty, x => indexes.indexOf(values.indexOf(x)))

现在我们只需要实现Comparison -

const Comparison =
  { empty: (a, b) =>
      a < b ? -1
        : a > b ? 1
          : 0
  , map: (m, f) =>
      (a, b) => m(f(a), f(b))
  }

const { empty, map } =
  Comparison

const sortByIndex = (values = [], indexes = []) =>
  map(empty, x => indexes.indexOf(values.indexOf(x)))

const fruits =
  [ "apple", "banana", "cherry", "orange", "peach" ]
  //   0        1          2        3         4 
  
const order =
  [ 1, 3, 2, 0, 4 ]

console.log(fruits)
// [ "apple", "banana", "cherry", "orange", "peach" ]

console.log(fruits.sort(sortByIndex(fruits, order)))
// [ "banana", "orange", "cherry", "apple", "peach" ]

为什么是模块?

实现Comparison 模块意味着我们有一个整洁的地方来存储我们所有的比较逻辑。我们现在可以轻松实现其他有用的功能,例如 reverseconcat -

const Comparison =
  { // ...
  , concat: (m, n) =>
      (a, b) => Ordered.concat(m(a, b), n(a, b))
  , reverse: (m) =>
      (a, b) => m(b, a)
  }

const Ordered =
  { empty: 0
  , concat: (a, b) =>
      a === 0 ? b : a
  }

现在我们可以轻松地为复杂的排序逻辑建模 -

const sortByName =
  map(empty, x => x.name)

const sortByAge =
  map(empty, x => x.age)

const data =
  [ { name: 'Alicia', age: 10 }
  , { name: 'Alice', age: 15 }
  , { name: 'Alice', age: 10 }
  , { name: 'Alice', age: 16 }
  ]

name排序,然后按age排序-

data.sort(concat(sortByName, sortByAge))
// [ { name: 'Alice', age: 10 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 16 }
// , { name: 'Alicia', age: 10 }
// ]

age排序,然后按name排序-

data.sort(concat(sortByAge, sortByName))
// [ { name: 'Alice', age: 10 }
// , { name: 'Alicia', age: 10 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 16 }
// ]

轻松reverse 任何分拣机。这里我们按name排序,然后按age反向排序-

data.sort(concat(sortByName, reverse(sortByAge)))
// [ { name: 'Alice', age: 16 }
// , { name: 'Alice', age: 15 }
// , { name: 'Alice', age: 10 }
// , { name: 'Alicia', age: 10 }
// ]

功能原则

我们的Comparison 模块既灵活又可靠。这允许我们以类似公式的方式编写分类器 -

// this...
concat(reverse(sortByName), reverse(sortByAge))

// is the same as...
reverse(concat(sortByName, sortByAge))

concat 表达式类似 -

// this...
concat(sortByYear, concat(sortByMonth, sortByDay))

// is the same as...
concat(concat(sortByYear, sortByMonth), sortByDay)

// is the same as...
nsort(sortByYear, sortByMonth, sortByDay)

nsort一起发疯

现在假设我们要按任意数量的因素进行排序。例如,对日期对象进行排序需要三个比较:yearmonthday -

const { empty, map, reverse, nsort } =
  Comparison

const data =
  [ { year: 2020, month: 4, day: 5 }
  , { year: 2018, month: 1, day: 20 }
  , { year: 2019, month: 3, day: 14 }
  ]

const sortByDate =
  nsort
    ( map(empty, x => x.year)  // primary: sort by year
    , map(empty, x => x.month) // secondary: sort by month
    , map(empty, x => x.day)   // tertiary: sort by day
    )

现在我们可以按yearmonthday 排序-

data.sort(sortByDate)
// [ { year: 2019, month: 11, day: 14 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2020, month: 4, day: 5 }
// ]

同样可以通过yearmonthday 轻松反向排序 -

data.sort(reverse(sortByDate))
// [ { year: 2020, month: 4, day: 5 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2019, month: 11, day: 14 }
// ]

得益于功能原理,实现 N 排序轻而易举。我们的concatempty 会尽心尽力-

const Comparison =
  { // ...
  , nsort: (...m) =>
      m.reduce(Comparison.concat, Comparison.empty)
  }

展开下面的 sn-p 以查看此代码的运行情况 -

const Comparison =
  { empty: (a, b) =>
      a < b ? -1
        : a > b ? 1
          : 0
  , map: (m, f) =>
      (a, b) => m(f(a), f(b))
  , concat: (m, n) =>
      (a, b) => Ordered.concat(m(a, b), n(a, b))
  , reverse: (m) =>
      (a, b) => m(b, a)
  , nsort: (...m) =>
      m.reduce(Comparison.concat, Comparison.empty)
  }

const Ordered =
  { empty: 0
  , concat: (a, b) =>
      a === 0 ? b : a
  }

const { empty, map, concat, reverse, nsort } =
  Comparison

const sortByDate =
  nsort
    ( map(empty, x => x.year)  // primary
    , map(empty, x => x.month) // secondary
    , map(empty, x => x.day)   // tertiary
    )

const data =
  [ { year: 2020, month: 4, day: 5 }
  , { year: 2019, month: 11, day: 14 }
  , { year: 2020, month: 4, day: 3 }
  ]

console.log(data.sort(reverse(sortByDate)))
// [ { year: 2020, month: 4, day: 5 }
// , { year: 2020, month: 4, day: 3 }
// , { year: 2019, month: 11, day: 14 }
// ]

JavaScript 模块

ComparisonOrdered 以上被定义为简单对象。 JavaScript 是一种非常灵活的语言,import/export 语法明确可用于模块化您的程序。以这种方式编写模块可以让我们清楚地了解事情的发展方向,并为我们提供足够的空间来发展我们的代码 -

// Comparison.js

import { lt, gt, eq, concat:_concat } from "./Ordered"

const asc = (a, b) =>
  (console.log(a, b), a < b) ? lt
    : a > b ? gt
      : eq

const empty =
  asc

const map =  (m, f) =>
  (a, b) => m(f(a), f(b))

const concat = (m, n) =>
  (a, b) => _concat(m(a, b), n(a, b))

const reverse = (m) =>
  (a, b) => m(b, a)

const desc =
  reverse(asc)

export { asc, concat, desc, empty, map, reverse }
// Ordered.js

const lt = 
  -1

const gt =
  1

const eq =
  0

const empty =
  eq

const concat = (a, b) =>
  a === eq ? b : a

export { concat, empty, eq, gt, lt }

【讨论】:

    【解决方案3】:

    很多代码,但它有效:)

    对于排序 ASC:

    var test = [1, 4, 3, 4, 5, 6, 7, 8, 9];
    console.log("Original Array: " + test);
    var len = test.length;
    var indices = new Array(len);
    for (var i = 0; i < len; ++i) indices[i] = i;
    indices.sort(function (a, b) { return test[a] < test[b] ? -1 : test[a] > test[b] ? 1 : 0; });
    test.sort();
    console.log("Sort-ASC " + test);
    console.log("Index from Array " + indices);

    对于 DESC 排序:

    var test = [1, 4, 3, 4, 5, 6, 7, 8, 9];
    console.log("Originales Array: " + test)
    var len = test.length;
    var indices = new Array(len);
    for (var i = 0; i < len; ++i) indices[i] = i;
    indices.sort(function (a, b) { return test[a] < test[b] ? -1 : test[a] > test[b] ? 1 : 0; });
    indices.reverse();
    test.sort();
    test.reverse();
    console.log("Sort-DESC " + test);
    console.log("Index from Array " + indices);

    【讨论】:

      【解决方案4】:

      它的朋友很容易使用这个 arr.sort(function(a, b){return a - b}); // 使用 return 否则它不会被触发和 - + 加号表示 ascndng dcndng ordee 简单的方法.....快乐编码

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-11-02
        • 1970-01-01
        • 1970-01-01
        • 2015-06-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多