简体   繁体   English

在 typescript 中以不同的权重对数组进行四次排序

[英]Sort array four times with different weighting in typescript

I want to sort an array four times, each time the sort-array-button is pressed a different status should be on top.我想对数组进行四次排序,每次按下排序数组按钮时,不同的状态应该在顶部。

0: {id: 1, status: "danger"}
1: {id: 2, status: "danger"}
3: {id: 3, status: "red"}
4: {id: 4, status: "red"}
5: {id: 5, status: "yellow"}
6: {id: 6, status: "yellow"}
7: {id: 7, status: "green"}

First click on the sort button: danger, danger, red, red, yellow, yellow, green second press: red, red, yellow, yellow, green, danger, danger third press: yellow, yellow, green, danger, danger, red, red fourth press: green, danger, danger, red, red, yellow, yellow and with the fifth press you are back to the first sort again danger, danger, red, red, yellow, yellow, green第一次点击排序按钮: danger, danger, red, red, yellow, yellow, green第二次按下: red, red, yellow, yellow, green, danger, danger第三次按下: yellow, yellow, green, danger, danger, red, red第四次按: green, danger, danger, red, red, yellow, yellow ,第五次按您又回到第一次danger, danger, red, red, yellow, yellow, green

Normally I sort arrays like this:通常我像这样对 arrays 进行排序:

myArray.sort((x, y) => x.status < y.status ? -1 : 1);

How can I extend the sort to give a color a higher value to make this work again?如何扩展排序以赋予颜色更高的值以使其再次起作用?

Normally I sort arrays like this通常我像这样排序 arrays

First we have to fix that.首先我们必须解决这个问题。 :-) You need to return 0 when x.status and y.status are the same. :-) 当x.statusy.status相同时,您需要返回0 In general, for strings it's (x, y) => x.status.localeCompare(y.status) and for numbers it's (x, y) => x.status - y.status (reverse x and y to switch from ascending to descending).一般来说,对于字符串它是(x, y) => x.status.localeCompare(y.status)而对于数字它是(x, y) => x.status - y.status (反转xy从升序切换下降)。

In your case, you want to assign values to the status types, and those values differ based on the click (apparently).在您的情况下,您希望为status类型分配值,并且这些值根据点击而有所不同(显然)。 To do that, give yourself mappings of status->number that you can pick based on what click it is:为此,请给自己映射 status->number ,您可以根据点击次数来选择:

const sortStyles = [
    {
        danger: 0,
        red: 1,
        yellow: 2,
        green: 3,
    },
    {
        red: 0,
        yellow: 1,
        green: 2,
        danger: 3,
    },
    {
        yellow: 0,
        green: 1,
        danger: 2,
        red: 3,
    },
    {
        green: 0,
        danger: 1,
        red: 2,
        yellow: 3,
    }
];

Then the sort is:那么排序是:

const style = sortStyles[index]; // index = 0 for first click, 1 for second, etc.
data.sort((x, y) => style[x.status] - style[y.status]));

Live Example:现场示例:

 const data = [ {id: 1, status: "danger"}, {id: 2, status: "danger"}, {id: 3, status: "red"}, {id: 4, status: "red"}, {id: 5, status: "yellow"}, {id: 6, status: "yellow"}, {id: 7, status: "green"} ]; const sortStyles = [ { danger: 0, red: 1, yellow: 2, green: 3, }, { red: 0, yellow: 1, green: 2, danger: 3, }, { yellow: 0, green: 1, danger: 2, red: 3, }, { green: 0, danger: 1, red: 2, yellow: 3, } ]; example("First click, sortStyles[0]:", data, sortStyles[0]); example("Second click, sortStyles[1]:", data, sortStyles[1]); example("Third click, sortStyles[2]:", data, sortStyles[2]); example("Fourth click, sortStyles[3]:", data, sortStyles[3]); function example(label, data, style) { console.log(label); console.log(data.slice().sort((x, y) => style[x.status] - style[y.status])); }

Conceptually (and not paying much attention to performance), you need to define an order for your status properties, and then rotate that order.从概念上讲(并且不太关注性能),您需要为您的status属性定义一个顺序,然后轮换该顺序。 You could do it like this:你可以这样做:

let order = ["danger", "red", "yellow", "green"];

function click() {
  order.push(order.shift()!)
  myArray.sort((x, y) => order.indexOf(x.status) - order.indexOf(y.status))
}

So when you call click() , the order array will take the first element off the list and push it onto the end.因此,当您调用click()时, order数组将从列表中取出第一个元素并将其推送到末尾。 And then you sort myArray based on the location of its status property in order (and if you are missing a status in order you can expect those to appear at the very front of the list no matter what; not sure what you want to do about edge cases like this, but you can handle them).然后根据其status属性的位置按ordermyArray进行排序(如果您按order缺少状态,则无论如何都可以期望这些状态出现在列表的最前面;不确定您要做什么像这样的边缘情况,但你可以处理它们)。

This gives the following behavior for this code:这为此代码提供了以下行为:

function show() {
  console.log(myArray.map(x => x.status).join(", "))
}

show();
for (let x = 0; x < 10; x++) {
  console.log("CLICK");
  click();
  show();
}

Console log:控制台日志:

danger, danger, red, red, yellow, yellow, green 
CLICK 
red, red, yellow, yellow, green, danger, danger 
CLICK 
yellow, yellow, green, danger, danger, red, red 
CLICK 
green, danger, danger, red, red, yellow, yellow 
CLICK 
danger, danger, red, red, yellow, yellow, green 
CLICK 
red, red, yellow, yellow, green, danger, danger 
CLICK 
yellow, yellow, green, danger, danger, red, red 
CLICK 
green, danger, danger, red, red, yellow, yellow 
CLICK 
danger, danger, red, red, yellow, yellow, green 
CLICK 
red, red, yellow, yellow, green, danger, danger 
CLICK 
yellow, yellow, green, danger, danger, red, red

Looks like what you want.看起来像你想要的。 Hope that helps;希望有帮助; good luck!祝你好运!

Playground link to code Playground 代码链接

Thank you all for your help.谢谢大家的帮助。 This is the working solution I'm using now.这是我现在正在使用的工作解决方案。

let sortStyle = {};
    switch (this.sortStatus) {
      case ('none'):
        sortStyle = {alert: 0, red: 1, yellow: 2, green: 3};
        this.myArray.sort((x, y) => sortStyle[x.status] - sortStyle[y.status]);
        this.sortStatus= 'alert';
        break;
      case ('alert'):
        sortStyle = {red: 0, yellow: 1, green: 2, alert: 3};
        this.myArray.sort((x, y) => sortStyle[x.status] - sortStyle[y.status]);
        this.myArray= 'red';
        break;
      case ('red'):
        sortStyle = {yellow: 0, green: 1, alert: 2, red: 3};
        this.myArray.sort((x, y) => sortStyle[x.status] - sortStyle[y.status]);
        this.sortStatus = 'yellow';
        break;
      case ('yellow'):
        sortStyle = {green: 0, alert: 1, red: 2, yellow: 3};
        this.myArray.sort((x, y) => sortStyle[x.status] - sortStyle[y.status]);
        this.sortStatus= 'green';
        break;
      case ('green'):
        sortStyle = {alert: 0, red: 1, yellow: 2, green: 3};
        this.myArray.sort((x, y) => sortStyle[x.status] - sortStyle[y.status]);
        this.sortStatus= 'alert';
        break;
      default:
        console.log('Error');
        break;
    }
  }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM