最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Sort array of object if value exists - Stack Overflow

programmeradmin2浏览0评论

Below is my sort function but I want to display the ones with a code to be at the top. I want to sort my array of objects by code, then by description. Right now, the items without a code is being placed at the top of the order.

data = [
 {
  code: "1.1",
  description: "aaa"
 },
 {
  code: "",
  description: "bbb"
 },
 {
  code: "1.2",
  description: "ccc"
 }
]


  let sortedData = data.sort(function(a, b) {
    let codeA = a.code
    let codeB = b.code
    let descriptionA = a.description.toLowerCase()
    let descriptionB = b.description.toLowerCase()

    if (codeA < codeB) return -1
    if (codeA > codeB) return 1
    if (descriptionA < descriptionB) return -1
    if (descriptionA > descriptionB) return 1
    return 0
  })

  return sortedData

Current order:

["bbb", "aaa", "ccc"]

Expected order:

["aaa", "ccc", "bbb"]

Below is my sort function but I want to display the ones with a code to be at the top. I want to sort my array of objects by code, then by description. Right now, the items without a code is being placed at the top of the order.

data = [
 {
  code: "1.1",
  description: "aaa"
 },
 {
  code: "",
  description: "bbb"
 },
 {
  code: "1.2",
  description: "ccc"
 }
]


  let sortedData = data.sort(function(a, b) {
    let codeA = a.code
    let codeB = b.code
    let descriptionA = a.description.toLowerCase()
    let descriptionB = b.description.toLowerCase()

    if (codeA < codeB) return -1
    if (codeA > codeB) return 1
    if (descriptionA < descriptionB) return -1
    if (descriptionA > descriptionB) return 1
    return 0
  })

  return sortedData

Current order:

["bbb", "aaa", "ccc"]

Expected order:

["aaa", "ccc", "bbb"]

Share Improve this question asked Feb 12, 2019 at 22:47 jj008jj008 1,1035 gold badges23 silver badges50 bronze badges
Add a ment  | 

4 Answers 4

Reset to default 4
  • Using the xor ^ operator, we can check to see if one of the codes is falsy while the other is truthy. In this case, falsy being blank. If this is true, the one with a blank should be greater than the other so it sorts after it.
  • Otherwise, subtract the codes, then the descriptions for normal sorting.

var data = [
 {
  code: "1.1",
  description: "aaa"
 },
 {
  code: "",
  description: "bbb"
 },
 {
  code: "1.2",
  description: "ccc"
 }
];


  let sortedData = data.sort(function(a, b) {
    let codeA = a.code;
    let codeB = b.code;
    let descriptionA = a.description.toLowerCase();
    let descriptionB = b.description.toLowerCase();
    
    if (codeA ^ codeB) {
      return !codeA ? 1 : -1;
    }
    
    return codeA.localeCompare(codeB) || descriptionA.localeCompare(descriptionB);
  });

  console.log(sortedData)

One way to make "" appear at the end is just to prefix the pare values, so if the code is "", the value bees "B", if it's 1.1 it bee A1.1, so A1.1 < B..

Doing this is also very easy to modify to do all sort of fancy sorting, eg. Lets say you wanted to sort alphabetically, but wanted all K's at the start, and all B's at the end, strange thing to do. But very easy to make happen. I suppose you could call it sorting with exceptions.

Here is a working example.

const data = [
 {
  code: "1.1",
  description: "aaa"
 },
 {
  code: "",
  description: "bbb"
 },
 {
  code: "1.2",
  description: "ccc"
 }
];

data.sort((
  { code: code1, description: desc1 },
  { code: code2, description: desc2 }
) => {
  code1 = (code1 === "" ? "B" : "A") + code1;
  code2 = (code2 === "" ? "B" : "A") + code2;
  return code1.localeCompare(code2) ||
    desc1.localeCompare(desc2);
});


console.log(data);

Your test case is a little lax and makes it hard to spot some bugs. You are usually better off using localeCompare to pare strings. You can make a case for two very plain, but readable if statements followed by a localeCompare of the strings:

Here's a few extra test cases

let data = [{
    code: "1.1",
    description: "ddd"
  },
  {
    code: "1.101",
    description: "ccc"
  },
  {
    code: "",
    description: "eee"
  },
  {
    code: "1.2",
    description: "De"
  },
  {
    code: "1.1",
    description: "aaa"
  },
  {
    code: "",
    description: "bbb"
  },
  {
    code: "1.2",
    description: "ccc"
  },
  {
    code: "1.2",
    description: "AbcD"
  }
]

data.sort((a, b) => {
  if (a.code && !b.code) return -1
  if (b.code && !a.code) return 1

  return a.code.localeCompare(b.code) || a.description.localeCompare(b.description)
})
console.log(data)

:

Since your second code is empty you will pare an empty string and Javascript will cast your Float to a String. Oddly if you pare any string if it is smaller than any other string it will always return true! The opposite is also true - if you pare it to be bigger than any other string it will always return false.

"" < "1.1" // return true
"1.1" < "" // return true!

"" > "1.1" // return false
"1.1" > "" // return false!

To solve your problem you could add two additional checks before your other checks

if (codeA === "" && codeA.length < codeB.length) return 1;
if (codeB === "" && codeA.length > codeB.length) return -1;

If codeA or codeB is a String you can simply pare the length of the strings.

发布评论

评论列表(0)

  1. 暂无评论