【问题标题】:How to sort array of objects based on a given sorted array containing values with Lodash?如何使用 Lodash 根据包含值的给定排序数组对对象数组进行排序?
【发布时间】:2019-06-10 16:21:47
【问题描述】:

使用 Lodash,我将如何根据给定的包含值的排序数组对对象数组进行排序?

例如,给定:

const movies = [
    {
        title: "La La Land",
        genre: "Musical"
    },
    {
        title: "Avengers",
        genre: "Action"
    },
    {
        title: "Chucky",
        genre: "Horror"
    }
]

const titles = [
    "Chucky",
    "La La Land",
    "Avengers"
]

我如何获得:

const sortedMovies = [
    {
        title: "Chucky",
        genre: "Horror"
    },
    {
        title: "La La Land",
        genre: "Musical"
    },
    {
        title: "Avengers",
        genre: "Action"
    }
]

哪个是按照titles数组中电影片名的排序顺序排序的?

【问题讨论】:

    标签: javascript ecmascript-6 lodash


    【解决方案1】:

    titles 创建一个Map (titlesByOrder),其中键是标题,值是原始数组的索引。然后使用_.sortBy(),并在回调中从titlesByOrder对象返回当前标题的值:

    const movies = [{"title":"La La Land","genre":"Musical"},{"title":"Avengers","genre":"Action"},{"title":"Chucky","genre":"Horror"}]
    const titles = ["Chucky","La La Land","Avengers"]
    
    const titlesByOrder = new Map(titles.map((t, i) => [t, i]))
    
    const result = _.sortBy(movies, o => titlesByOrder.get(o.title))
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

    如果titles数组包含movies中所有项目的标题,并且项目标题是唯一的,则可以使用_.keyBy()movies数组转换为对象,然后得到一个数组使用_.at()的正确顺序:

    const movies = [{"title":"La La Land","genre":"Musical"},{"title":"Avengers","genre":"Action"},{"title":"Chucky","genre":"Horror"}]
    const titles = ["Chucky","La La Land","Avengers"]
    
    const result = _.at(
      _.keyBy(movies, 'title'),
      titles
    )
    
    console.log(result)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

    【讨论】:

      【解决方案2】:

      你可能不需要 lodash。请检查以下解决方案是否有用。

      const movies = [
        {
          title: "La La Land",
          genre: "Musical"
        },
        {
          title: "Avengers",
          genre: "Action"
        },
        {
          title: "Chucky",
          genre: "Horror"
        }
      ];
      
      const titles = ["Chucky", "La La Land", "Avengers"];
      const orderMap = titles.reduce((acc, data, index) => {
        acc[data] = titles.length - index;
        return acc;
      }, {});
      x = movies.sort((x, y) => {
        const orderOfX = titles.length - orderMap[x.title];
        const orderOfY = titles.length - orderMap[y.title];
        return orderOfX - orderOfY;
      });
      console.log(x);

      【讨论】:

      • 您可以从所有表达式中删除titles.length - ,仍然得到相同的结果。
      【解决方案3】:

      您可以通过Array.indexOf 简单地检查索引并通过Array.sort 进行比较。无需为此使用 lodash:

      const movies = [{"title":"La La Land","genre":"Musical"},{"title":"Avengers","genre":"Action"},{"title":"Chucky","genre":"Horror"}]
      const titles = ["Chucky","La La Land","Avengers"]
      
      let result = movies.sort((a,b) => titles.indexOf(a.title) - titles.indexOf(b.title))
      
      console.log(result)
      

      除非您要处理这些数组中的数十万个条目,否则性能应该不是问题。但是,如果您需要高性能的,您可以通过简化为简单的 key/value 对来实现,其中您的键是 string,值是 index in the array

      const movies = [{"title":"La La Land","genre":"Musical"},{"title":"Avengers","genre":"Action"},{"title":"Chucky","genre":"Horror"}]
      const titles = ["Chucky","La La Land","Avengers"]
        .reduce((acc,c,i) => (acc[c] = i, acc), {}) // reduce to a key/value pairs
      
      let result = movies.sort((a,b) => titles[a.title] - titles[b.title]) // sort by index
      
      console.log(result)

      【讨论】:

        猜你喜欢
        • 2018-11-03
        • 2017-09-08
        • 2019-07-26
        • 2016-09-01
        • 2013-11-25
        • 1970-01-01
        • 2018-11-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多