首页 > 解决方案 > 基于多个条件的 Javascript 数组排序(一次迭代)

问题描述

我有一系列汽车:

enum Condition {
  New = 1,
  Used = 2
}

type Car = {
  make: string;
  model: string;
  age: number;
  condition: Condition;
};

const cars: Car[] = [
  {id: "1", make: "BMW", model: "E3", age: 12, condition: Condition.Used},
  {id: "2", make: "Audi", model: "A8", age: 4, condition: Condition.Used},
  {id: "3", make: "Mercedes", model: "SLK", age: 0, condition: Condition.New},
  {id: "4", make: "Ford", model: "CMAX", age: 3, condition: Condition.Used},
  {id: "5", make: "Ford", model: "BMAX", age: 0, condition: Condition.New},
  {id: "6", make: "Porsche", model: "Panamera", age: 0, condition: Condition.New},
]

我有一个搜索查询:

const searchQuery: Car = {
  make: "Ford",
  model: "Panamera",
  age: 4,
  condition: Condition.New
}

我想有一个基于这些规则的排序数组:

首先,我所做的是过滤与品牌匹配的数组,然后是模型,然后是年龄等......然后将结果数组合并到最终数组(也过滤掉通过多个条件的重复项),但这需要迭代超过cars我所拥有的标准数量的多次。所以我想知道是否有更好的方法可以一次性完成?也许以.sort某种方式使用?

标签: javascriptarrayssorting

解决方案


您可以创建一个映射函数来确定您的优先级,并在您的排序中减去标准化值。

const Condition = { New: 1, Used: 2 };

const cars = [
  {id: "1", make: "BMW", model: "E3", age: 12, condition: Condition.Used},
  {id: "2", make: "Audi", model: "A8", age: 4, condition: Condition.Used},
  {id: "3", make: "Mercedes", model: "SLK", age: 0, condition: Condition.New},
  {id: "4", make: "Ford", model: "CMAX", age: 3, condition: Condition.Used},
  {id: "5", make: "Ford", model: "BMAX", age: 0, condition: Condition.New},
  {id: "6", make: "Porsche", model: "Panamera", age: 0, condition: Condition.New},
];

const searchQuery = {
  make: "Ford",
  model: "Panamera",
  age: 4,
  condition: Condition.New
};

const prioritize = (car, query) => {
  if (car.make === query.make) return 4;
  if (car.model === query.model) return 3;
  if (car.age === query.age) return 2;
  if (car.condition === query.condition) return 1;
  
  return 0;
};

const sorted = cars.sort((a, b) => {
  const prioA = prioritize(a, searchQuery);
  const prioB = prioritize(b, searchQuery);

  return prioB - prioA;
});

console.log(JSON.stringify(sorted, null, 2));

如果您希望排序适用于多个条件,例如第一个品牌和型号,您可以添加一个简单的递归检查并增加优先级:

const prioritize = (car, query) => {
  const { make, model, age, condition } = query;

  if (car.make === make) return 4 + prioritize(car, { model, age, condition });
  if (car.model === model) return 3 + prioritize(car, { age, condition });
  if (car.age === age) return 2 + prioritize(car, { condition });
  if (car.condition === condition) return 1;

  return 0;
};

在这里,您只需检查下一行的其他查询选项。


推荐阅读