从字典数组中获取按日期排序的最近两个项目

时间:2018-10-15 02:15:11

标签: javascript typescript

曾经看过类似的话题,但无法将我的头缠住。即使对我来说,我当前的项目似乎也更复杂。这是我的json(抱歉,它有点长):

items = [
      {
        'name' : 'Books',
        'types':[
          {
              'name' : 'Hard Cover',
              'genres':[
                {
                  'genre' : 'Romance',

                  'added_date' : '2018-09-15',

                  'id':1
                },
                {
                  'genre' : 'Crime',

                  'added_date' : '2018-10-01',

                  'id' : 2
                }

              ],
              'cover':['pic1.png','pic2.png']
              },
              {
                'name' : 'Audio',
                'genres':[
                  {
                    'genre' : 'Memoir',

                    'added_date' : '2018-08-01',

                    'id' : 3
                  }

                ],
                'pictures':['pic3.png','pic4.png']
           },

         ]

      },

      {
        'name' : 'Videos',
        'types':[
          {
              'name' : 'English',
              'genres':[
                {
                  'genre' : 'Comedy',

                  'added_date' : '2018-10-14',

                  'id' : 12
                }

              ],
              'pictures':['pic5.png','pic6.png']
              }

         ]

      }
  ];

我现在想要的输出是根据流派块中的added_date字段获取最近添加的3个项目。现在,对于这些项目,我需要返回带有完整路径的字典元素的数组:

   [
    {'id':7,'genre':'Romance','name':'Hard Cover','added_date':'2018-09-16','top_parent_name':'Books'},
    {'id':8,'genre':'Memoir','name':'Audio','added_date':'2018-09-15','top_parent_name':'Books'},


     ]

基于add_date,获取通过整个对象及其相关信息添加的最新3个项目。我希望这是有道理的。

到目前为止,我已经想到了以下内容,但很快就变得很麻烦。

items.forEach(function(value, index, array) {
      const types: any[] = value['types'];

      types.forEach(function(value_t, index_t, array_t){
        const genres: any[] = value_model['genes'];
       //loop again to get date....

      });



  });

2 个答案:

答案 0 :(得分:3)

这是一种方法。首先,通过执行多个级别的映射然后进行多个级别的扁平化,将所需的数据提取到对象中。 (我相信Array.prototype.flatten尚不普及,所以我使用reduce(concat)。)

然后,当您将数据提取到平面列表中时,将其按日期降序排序。最后,获取前三个值:

const items = [{"name": "Books", "types": [{"cover": ["pic1.png", "pic2.png"], "genres": [{"added_date": "2018-09-15", "genre": "Romance", "id": 1}, {"added_date": "2018-10-01", "genre": "Crime", "id": 2}], "name": "Hard Cover"}, {"genres": [{"added_date": "2018-08-01", "genre": "Memoir", "id": 3}], "name": "Audio", "pictures": ["pic3.png", "pic4.png"]}]}, {"name": "Videos", "types": [{"genres": [{"added_date": "2018-10-14", "genre": "Comedy", "id": 12}], "name": "English", "pictures": ["pic5.png", "pic6.png"]}]}];

const tops = items.map(item => item.types.map(type => type.genres.map(genre => ({
  name: type.name,
  top_name: item.name,
  ...genre
})))).reduce(
  (a, b) => a.concat(b), []
).reduce(
  (a, b) => a.concat(b), []
).sort(
  (a, b) => a.added_date > b.added_date ? -1 : a.added_date < b.added_date ? 1 : 0
).slice(0, 3)

console.log(tops)

在这些单独的循环中肯定存在一些效率低下的情况,排序可能是O(n * log(n)),而即使是三部分的最大值也应该是O(n)。但是,只有在您的应用程序出现瓶颈时,我才会担心这些问题。

答案 1 :(得分:2)

因此,如果我正确地理解了这个问题,则您希望按日期添加最新的3个值,并将其展平为特定格式。如果是这样,那么答案可能取决于您正在处理多少数据。一种选择是构建完全平面的数据数组,然后按日期排序。为此,我将使用数组展平实用程序功能(我已包含其中一个,但如果可以,请使用lodash)

例如:

const flatten = arr => arr.reduce((a, b) => a.concat(b), [])

const mapGenres = (topName, name, genres) => genres.map(genre => ({
  name,
  topName,
  ...genre
})

const result = flatten(items.map(({ name, types }) => 
  flatten(types.map(type => mapGenres(name, type.name, type.genres)))
))

result.sort((a, b) => return b.added_date.localeCompare(a.added_date))

这未经测试,但应该很简单。拼合贴图的嵌套级别,在叶子上产生所需的输出。