【问题标题】:Sort array of objects based on user input根据用户输入对对象数组进行排序
【发布时间】:2020-11-17 08:35:32
【问题描述】:

我有一个世界城市的大型数据集(一个数组中的 100K+ 个对象)和一个用户的位置信息。我想按用户的位置对世界城市数组进行排序,并返回前 7 个(或许多)最相关的匹配项。

例如,如果用户位于美国加利福尼亚州的纽波特海滩,我想对美国所有“纽波特海滩”城市首先出现的数组进行排序,并将用户的确切位置作为第一个结果数组。

用户的位置通过 API 传入,并保存到局部变量中:

const userCity = "Newport Beach";
const userState = "CA";
const userCountry = "United States";

原始数组保存到名为allCities 的变量中。我对这个数组进行如下排序:

allCities
  .sort((a, b) => b.city.startsWith(userCity) - a.city.startsWith(userCity))
  .sort((a, b) => b.state && b.state.startsWith(userState) - a.state && a.state.startsWith(userState)) // This should only apply to the U.S.
  .sort((a, b) => b.country.startsWith(userCountry) - a.country.startsWith(userCountry));

结果,我 slicing 只返回前 7 个匹配项:

const list = [
  { city: 'Newport', state: 'AR', country: 'United States' },
  { city: 'Chevy Chase Village',
    state: 'MD',
    country: 'United States' },
  { city: 'Newport', state: 'NH', country: 'United States' },
  { city: 'Newport', state: 'ME', country: 'United States' },
  { city: 'Newport', state: 'TN', country: 'United States' },
  { city: 'Newport', state: 'SC', country: 'United States' },
  { city: 'Newport', state: 'IN', country: 'United States' }
]

这里的问题是“CA”中的“Newport Beach”甚至没有出现。用户不必输入他们所在城市的全名。在前几个字符之后,他们的位置应该是第一个结果,就像 IntelliSense 功能一样,因为我已经有了他们的信息。

我也不知道当“Newport Beach”是搜索词时,MD 中的 Chevy Chase Village 是如何出现在搜索结果中的。

第一个结果应该是用户的确切城市、州(如果他们在美国)和国家/地区。第二个结果应该是相同的城市和国家,但不同的州(同样,如果它们在美国)。最后,同一个城市,但其他国家。如果没有找到匹配项,我会通知用户。

需要注意的是,我有一个在浏览器中完美运行的版本:

allCities
  // Show closest matching cities first
  .sort(location => userLocationData && location.city === userLocationData.city ? -1 : 1)
  // Show exact matches based on city length
  .sort((a, b) => a.city.length - b.city.length)
  // Show closest matching countries
  .sort(location => userLocationData && location.country === userLocationData.country ? -1 : 1)
  // Show closest matching states
  .sort(location => userLocationData && location.state === userLocationData.region ? -1 : 1);

这种方法的问题是allCities 数组有超过 100K 的对象(超过 8 MB),所以它不会在慢速连接上加载。在设备上加载这么多数据也可能并不理想。

当我尝试在服务器中使用此逻辑时,它无法运行。我想这是因为sort() 需要两个参数,而在这里,我只提供一个。 SO 上提供的其他问题/答案(如this one)很有帮助,但似乎没有一个能解决问题。

如何根据用户输入对该数组进行排序以达到预期的结果?

【问题讨论】:

  • 听起来你应该先按完全匹配排序
  • 每次拨打.sort()都会丢失之前的订单。
  • 查看stackoverflow.com/questions/7160263/…了解如何按多个条件排序。
  • 你需要一个稳定的排序,例如看stackoverflow.com/questions/1427608/…
  • @Nick 即使使用稳定的排序,按城市名称的长度排序(例如)之后按位置排序将使第一个排序结果无效。用户可能在 Alomogordo,因此 Peoria 的所有记录将排在第一位。

标签: javascript node.js sorting


【解决方案1】:

我发现了一些有用的东西。

allCities.sort((a, b) => {
  if (b.city.startsWith(userCity) > a.city.startsWith(userCity)) return 1;
  if (b.city.startsWith(userCity) < a.city.startsWith(userCity)) return -1;

  if (b.country.startsWith(userCountry) > a.country.startsWith(userCountry)) return 1;
  if (b.country.startsWith(userCountry) < a.country.startsWith(userCountry)) return -1;

  if (a.state === b.state) {
    return 0;
  } else if (a.state === null) {
    return 1;
  } else if (b.state === null) {
    return -1;
  } else {
    return b.state.startsWith(userState) - a.state.startsWith(userState);
  }
})

此解决方案将采用用户的位置:城市、州(如果存在)和国家/地区。它将首先按完全匹配的城市进行排序,然后按国家/地区首先仅显示用户的国家/地区,最后按州显示该用户所在国家/地区不同州的匹配城市。我找到了状态解决方案here。我在这方面花了太长时间,所以希望这对其他人也有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-10-22
    • 1970-01-01
    • 2021-08-09
    • 2013-11-25
    • 2020-12-15
    • 1970-01-01
    • 1970-01-01
    • 2019-03-28
    相关资源
    最近更新 更多