【问题标题】:Sort function with undefined value具有未定义值的排序函数
【发布时间】:2022-01-13 23:31:34
【问题描述】:

我有一个对象数组,如下所示:

 var stores = [
      {
        "name": "store3",
        "ditance": 8
      },
      {
        "name": "Store5",
        "distance": 7,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isFutureOrderPossible": false
          }
        }
      },
      {
        "name": "Store1",
        "distance": 12,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isOpen": true
          }
        }
      },
      {
        "name": "store2",
        "distance": 13,
        "web": {
          "validateAttributes": {
            "isSelectedDispostionSupported": true,
            "isOpen": true
          }
        }
      }
    ]

根据 isopen 和距离排序的预期结果

[
  {
    "name": "Store1",
    "distance": 12,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isOpen": true
      }
    }
  },
  {
    "name": "store2",
    "distance": 13,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isOpen": true
      }
    }
  },
  {
    "name": "Store5",
    "distance": 7,
    "web": {
      "validateAttributes": {
        "isSelectedDispostionSupported": true,
        "isFutureOrderPossible": false
      }
    }
  },
  {
    "name": "store3",
    "ditance": 8
  }
]

需要根据 isOpen 和 distance 对数组进行排序。挑战是一些对象有网络属性,而一些对象没有。即使网络有时可用 isOpen 也不会。我已经尝试了以下方法它不起作用

const sorter = (a, b) => {
                if (a.web) {
                  if (a.web.validateAttributes) {
                    if (a.web.validateAttributes.isOpen) {
                      return 1;
                    } else if (b.web.validateAttributes.isOpen) {
                      return -1;
                    } else {
                      return 1;
                    };
                  } else {
                    return 1;
                  }
                 
                } else {
                  return 1;
                }
              };
  stores.sort(sorter);

【问题讨论】:

  • 预期的结果应该是什么?请自行添加问题...
  • @decpk 提供
  • 你真的只有一个条目有ditance 属性吗?
  • @Phil 距离也是他们的。需要先根据isOpen和距离排序

标签: javascript arrays angular sorting filtering


【解决方案1】:

在这里修正了一些错别字之后是另一种选择。

如果未设置,则默认每个 isOpenfalse 并存储。 如果相同,则按distance 排序,否则按isOpen 排序。

这使用了Optional Chaining operatorNullish Coalescing operator 的组合

如果链上的任何属性不存在,可选链运算符将返回null。因此,在.web.isOpen 不存在的情况下,会生成null

后面是 Nullish Caolescing 运算符,因此如果如上所述生成 null,则默认值为 false,因此排序顺序基于该值(true 将放置在 @987654334 之前@。

let stores = [{"name":"Store1","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"Store5","distance":8,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"store3","distance":7}];

function comparator(a,b) {
  let aResult = a?.web?.validateAttributes?.isOpen ?? false;
  let bResult = b?.web?.validateAttributes?.isOpen ?? false;
  return (aResult === bResult)? a.distance - b.distance : bResult - aResult;
}
console.log(stores.sort(comparator));

【讨论】:

    【解决方案2】:

    试试这个

    const stores = [{"name":"store3","ditance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]
    
       const sorter = (a,b)=> {
          if(!b.web) {
              return -1;
          }
          else if(!b.web.validateAttributes) {
            return -1;
          }
          else if(!b.web.validateAttributes.isOpen) {
            return -1;
          }
          return (a.distance - b.distance)
       }
       console.log(stores.sort(sorter)) 

    【讨论】:

      【解决方案3】:

      试试这个。

      const stores = [{"name":"store3","ditance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]
      
      const sorted = stores.slice();
      
      sorted.sort((a, b) => {
          if (!a.web || !b.web) {
              return -1;
          }
          if (!a.web.validateAttributes || !b.web.validateAttributes) {
              return -1;
          }
          const x = a.web.validateAttributes.isOpen || false;
          const y = b.web.validateAttributes.isOpen || false;
      
          return (x === y) ? a.distance - b.distance : -1;
      })
      console.log(sorted)
      .as-console-wrapper { max-height: 100% !important; top: 0; }

      【讨论】:

        【解决方案4】:

        我发现了 2 个问题。

        1. 第一项“距离”的错字:8
        2. 您的排序功能。 这是我的逻辑。首先,检查两者是Opening 还是Closing,然后比较距离。 否则只是简单地比较状态打开/关闭

        var stores = [{"name":"store3","distance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}];
            
        stores.sort((a, b) => {
          if (a.web?.validateAttributes?.isOpen && b.web?.validateAttributes?.isOpen || !a.web?.validateAttributes?.isOpen && !b.web?.validateAttributes?.isOpen) {
            return a.distance - b.distance;
          }
          if (a.web?.validateAttributes?.isOpen) {
            return -1;
          }
          return 1;
        })
        
        console.log(stores);

        【讨论】:

          【解决方案5】:

          您可以使用一些optional chainingisOpen 属性转换为-1 如果真实 或1 如果虚假 来确定它们的位置。

          如果这些属性相等,则回退到距离比较。

          // fixed "ditance" to "distance" in "store3"
          const stores = [{"name":"store3","distance":8},{"name":"Store5","distance":7,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isFutureOrderPossible":false}}},{"name":"Store1","distance":12,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}},{"name":"store2","distance":13,"web":{"validateAttributes":{"isSelectedDispostionSupported":true,"isOpen":true}}}]
          
          const sorted = [...stores].sort((a, b) => 
            (a.web?.validateAttributes?.isOpen ? -1 : 1) -
            (b.web?.validateAttributes?.isOpen ? -1 : 1) ||
            (a.distance - b.distance))
            
          console.log(sorted)
          .as-console-wrapper { max-height: 100% !important; }

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2015-01-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-11-25
            相关资源
            最近更新 更多