将空值放在数据排序的最后。

huangapple go评论76阅读模式
英文:

place null values at last while sorting the data

问题

I have this data which I'm displaying in the table:

[
{
"ID": 9,
"Status": "Pending",
},
{
"ID": 8,
"Status": null,
},
{
"ID": 7,
"Status": "Pending",
},
{
"ID": 10,
"Status": null,
},
{
"ID": 18,
"Status": "Completed",
},
{
"ID": 17,
"Status": "In Progress",
}
]

Sort Method:

Ascending order:

this.List.sort((a, b) => a[columnname] < b[columnname] ? 1 : a[columnname] > b[columnname] ? -1 : 0);

Descending order:

this.List.sort((a, b) => a[columnname] > b[columnname] ? 1 : a[columnname] < b[columnname] ? -1 : 0);

and using the sort function to sort the data in the table. The issue is when I sort it, I want to place null values at the end. In the current scenario, they are in between other values.

Like:

Completed
null
In Progress
null
Pending
null
...

英文:

I have this data which i'm displaying in the table

[
    {
        &quot;ID&quot;: 9,
        &quot;Status&quot;: &quot;Pending&quot;,
    },
    {
        &quot;ID&quot;: 8,
        &quot;Status&quot;: null,
    },
    {
        &quot;ID&quot;: 7,
        &quot;Status&quot;: &quot;Pending&quot;,
    },
    {
        &quot;ID&quot;: 10,
        &quot;Status&quot;: null,
    },
    {
        &quot;ID&quot;: 18,
        &quot;Status&quot;: &quot;Completed&quot;,
    },
    {
        &quot;ID&quot;: 17,
        &quot;Status&quot;: &quot;In Progress&quot;,
    }
]

Sort Method:

> Ascending order :

 this.List.sort((a, b) =&gt; a[columnname] &lt; b[columnname] ? 1 : a[columnname] &gt; b[columnname]` ? -1 : 0);

> Descending order :

 this.List.sort((a, b) =&gt; a[columnname] &gt; b[columnname] ? 1 : a[columnname] &lt; b[columnname] ? -1 : 0);

and using sort function to sort the data in table issue is when i sort it, i want to place null values at the last. In current scenario they are in between other values

Like

Completed
null
In Progress
null
Pending 
null 
..

答案1

得分: 2

这是你的排序函数的一些要点
* 你不应该使用 `&lt;`  `&gt;` 来比较字符串它会导致在大小写特殊字符数字等方面出现奇怪的结果可以使用 `String.localeCompare` 函数来比较字符串
* 如果你希望始终将 `null`或其他特殊值放在末尾可以让它返回一个始终相同的自定义值

这是一个示例排序函数其中包含了对数字和字符串的检查并始终将 null 值一起排序

```javascript
function mySort(data, columnName, reverse) {
    return data.sort((a, b) => {
        const valueA = reverse ? a[columnName] : b[columnName];
        const valueB = reverse ? b[columnName] : a[columnName];

        if (valueA === null) {
            return -1;
        }
        if (typeof valueA === 'string' && typeof valueB === 'string') {
            return valueA.localeCompare(valueB);
        }
        if (typeof valueA === 'number' && typeof valueB === 'number') {
            return valueA - valueB;
        }
    })
}

如果你调用 mySort(list, 'Status', false),你会注意到所有的 null 值都在末尾,而其余部分仍然被正确排序。

如果你想要在升序和降序排序中都将 null 放在末尾,你可以将特殊的 === null 检查适应成类似以下方式:

if (valueA === null) {
   return reverse ? 1 : -1;
}
英文:

Couple of things for your sorting function

  • You should not use &lt; and &gt; to compare strings. It does weird things with upper/lower case, special characters, numbers, etc. there is a String.localeCompare function that can be used to compare strings
  • If you want to sort null (or other special values) always at the end, just let it return a custom value that is always the same

This is a sample sorting function, that contains a check for number & string and always sorts null values together

function mySort(data, columnName, reverse) {
    return data.sort((a, b) =&gt; {
        const valueA = reverse ? a[columnName] : b[columnName];
        const valueB = reverse ? b[columnName] : a[columnName];

        if (valueA === null) {
            return -1;
        }
        if (typeof valueA === &#39;string&#39; &amp;&amp; typeof valueB === &#39;string&#39;) {
            return valueA.localeCompare(valueB);
        }
        if (typeof valueA === &#39;number&#39; &amp;&amp; typeof valueB === &#39;number&#39;) {
            return valueA - valueB;
        }
    })
}

if you call mySort(list, &#39;Status&#39;, false) you will notice that all the null values are at the end while the rest is still properly sorted.

If you want to have null in the end for both descending and ascending you can adapt the special === null check to something like

if (valueA === null) {
   return reverse ? 1 : -1;
}

答案2

得分: 1

以下是您要翻译的内容:

const tasks = [
  { "ID":  9, "Status": "Pending"     },
  { "ID":  8, "Status":  null         },
  { "ID":  7, "Status": "Pending"     },
  { "ID": 10, "Status":  null         },
  { "ID": 18, "Status": "Completed"   },
  { "ID": 17, "Status": "In Progress" },
];

const columnName = "Status";
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
  (a == null) - (b == null) // move null values to the back of the array
  || -(a < b)               // move `a` to the front if it's smaller than `b`
  || +(a > b)               // move `a` to the back if it's greater than `b`
));

console.log(tasks);
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
  if (a == null && b != null) return  1; // a after b
  if (a != null && b == null) return -1; // a before b
  if (a < b) return -1; // a before b
  if (a > b) return  1; // a after b
  return 0; // equal
});
const modifiers = { asc: 1, desc: -1 };
const columnName = "Status";
const direction = "desc";

tasks.sort(({ [columnName]: a }, { [columnName]: b }) => (
  (a == null) - (b == null) // move null values to the back of the array
  || modifiers[direction] * (
    -(a < b)                // move `a` to the front if it's smaller than `b`
    || +(a > b)             // move `a` to the back if it's greater than `b`
  )
));
tasks.sort(({ [columnName]: a }, { [columnName]: b }) => {
  if (a == null && b != null) return  1; // a after b
  if (a != null && b == null) return -1; // a before b
  if (a < b) return -1 * modifiers[direction]; // a before b
  if (a > b) return  1 * modifiers[direction]; // a after b
  return 0; // equal
});
英文:

A fairly short way to do this would be:

<!-- begin snippet: js hide: false console: true babel: false -->

<!-- language: lang-js -->

const tasks = [
  { &quot;ID&quot;:  9, &quot;Status&quot;: &quot;Pending&quot;     },
  { &quot;ID&quot;:  8, &quot;Status&quot;:  null         },
  { &quot;ID&quot;:  7, &quot;Status&quot;: &quot;Pending&quot;     },
  { &quot;ID&quot;: 10, &quot;Status&quot;:  null         },
  { &quot;ID&quot;: 18, &quot;Status&quot;: &quot;Completed&quot;   },
  { &quot;ID&quot;: 17, &quot;Status&quot;: &quot;In Progress&quot; },
];

const columnName = &quot;Status&quot;;
tasks.sort(({ [columnName]: a }, { [columnName]: b }) =&gt; (
  (a == null) - (b == null) // move null values to the back of the array
  || -(a &lt; b)               // move `a` to the front if it&#39;s smaller than `b`
  || +(a &gt; b)               // move `a` to the back if it&#39;s greater than `b`
));

console.log(tasks);

<!-- end snippet -->

In the snippet above we start with destructuring both comparator objects. ({ [columnName]: a }, { [columnName]: b }) stores the value of the columnName property of the first argument in the variable a and b for the second argument.

We then start with (a == null) - (b == null) to move the null values to the back of the array. This works because true coerces into 1 and false coerces into 0. So if a is null and b is not, then true - false will evaluate to 1 - 0 //=&gt; 1. A positive return value means that a is placed behind b. If we are in the opposite scenario and a is not null but b is, then false - true //=&gt; -1. A negative return value means that a is placed before b.

Both 1 or -1 are truthy values, which cause the OR operator || to short circuit and return the first operand. If both values are null or both values are not null, then we end up with true - true or false - false which both evaluate to 0. Since 0 is a falsy value, we'll move on to the second operand of the OR operator.

This brings us to -(a &lt; b), which checks if a is smaller than b. When this is true -true will evaluate into -1, so a is placed before b. If this is false then -false will evaluate into -0, which is a falsy value and moves us to the next operand in the OR chain. Assume that a and b are both null, then null &lt; null is false, thus moving us on to the next OR operand. If a and b are both not null, say the status string, then the strings are compared based on code point values and -1 is returned if a is smaller than b. Otherwise we move on to the final OR operand.

+(a &gt; b) is very similar to -(a &lt; b), but returns 1 if a is greater than b. Placing a after b in the result.

Here are 6 example scenarios, showing the different outputs:

a = null, b = null
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  0  ─────────┘    └─ -0 ─┘    └─  0 ─┘ */
//=&gt;  0   a and b are equal

a = null, b = &quot;a&quot;
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  1  ─────────┘                         */
//=&gt;  1   a is placed after b

a = &quot;a&quot;, b = null
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  -1  ─────────┘                        */
//=&gt; -1   a is placed before b

a = &quot;a&quot;, b = &quot;a&quot;
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  0  ─────────┘    └─ -0 ─┘    └─  0 ─┘ */
//=&gt;  0    a and b are equal

a = &quot;a&quot;, b = &quot;b&quot;
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  0  ─────────┘    └─ -1 ─┘             */
//=&gt; -1    a is placed before b

a = &quot;b&quot;, b = &quot;a&quot;
(a == null) - (b == null) || -(a &lt; b) || +(a &gt; b) /*
└─────────  0  ─────────┘    └─ -0 ─┘    └─  1 ─┘ */
//=&gt;  1    a is placed after b

A less cryptic version could be written like so:

tasks.sort(({ [columnName]: a }, { [columnName]: b }) =&gt; {
  if (a == null &amp;&amp; b != null) return  1; // a after b
  if (a != null &amp;&amp; b == null) return -1; // a before b
  if (a &lt; b) return -1; // a before b
  if (a &gt; b) return  1; // a after b
  return 0; // equal
});

To apply an asc/desc direction, but keep the null values at the back of the array, you can apply a modifier to the second part to inverse the sign (in case of a descending direction).

const modifiers = { asc: 1, desc: -1 };
const columnName = &quot;Status&quot;;
const direction = &quot;desc&quot;;

tasks.sort(({ [columnName]: a }, { [columnName]: b }) =&gt; (
  (a == null) - (b == null) // move null values to the back of the array
  || modifiers[direction] * (
    -(a &lt; b)                // move `a` to the front if it&#39;s smaller than `b`
    || +(a &gt; b)             // move `a` to the back if it&#39;s greater than `b`
  )
));

// without comments
tasks.sort(({ [columnName]: a }, { [columnName]: b }) =&gt; (
  (a == null) - (b == null) || modifiers[direction] * (-(a &lt; b) || +(a &gt; b))
));

Or:

tasks.sort(({ [columnName]: a }, { [columnName]: b }) =&gt; {
  if (a == null &amp;&amp; b != null) return  1; // a after b
  if (a != null &amp;&amp; b == null) return -1; // a before b
  if (a &lt; b) return -1 * modifiers[direction]; // a before b
  if (a &gt; b) return  1 * modifiers[direction]; // a after b
  return 0; // equal
});

huangapple
  • 本文由 发表于 2023年4月13日 22:55:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76006927.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定