2016-12-24 4 views
4

Например, у меня есть массив как это:Как выбрать последний элемент для каждого пользователя из массива?

[ 
{ 
    "data": "some data", 
    "user": "A", 
    "createdAt":"2016-12-24", 
}, 
{ 
    "data": "some data2", 
    "user": "B", 
    "createdAt":"2016-12-24", 
}, 
{ 
    "data": "some data3", 
    "user": "A", 
    "createdAt":"2016-12-25", 
}, 
{ 
    "data": "some data4", 
    "user": "A", 
    "createdAt":"2016-12-23", 
}, 
{ 
    "data": "some data5", 
    "user": "B", 
    "createdAt":"2016-12-25", 
}, 
{ 
    "data": "some data6", 
    "user": "C", 
    "createdAt":"2016-12-24", 
}, 
] 

Мне нужно только последний созданный элемент за одного пользователя, так что мне нужен массив так:

[ 
{ 
    "data": "some data3", 
    "user": "A", 
    "createdAt":"2016-12-25", 
}, 
{ 
    "data": "some data5", 
    "user": "B", 
    "createdAt":"2016-12-25", 
}, 
{ 
    "data": "some data6", 
    "user": "C", 
    "createdAt":"2016-12-24", 
}, 
] 

Как я могу это сделать с подчеркиванием или lodash?

ответ

2

lodash предоставляет методы orderBy и uniqBy.

Ключ должен быть заказан user, затем createdAt в порядке убывания. Поскольку createdAt является Date, его необходимо рассматривать как таковой. Соответственно, метод orderBy позволяет указать либо свойство для заказа, либо функцию для оценки (которая возвращает объект для заказа, в данном случае Date).

var data = [{ 
 
     "data": "some data", 
 
     "user": "A", 
 
     "createdAt": "2016-12-24", 
 
    }, { 
 
     "data": "some data2", 
 
     "user": "B", 
 
     "createdAt": "2016-12-24", 
 
    }, { 
 
     "data": "some data3", 
 
     "user": "A", 
 
     "createdAt": "2016-12-25", 
 
    }, { 
 
     "data": "some data4", 
 
     "user": "A", 
 
     "createdAt": "2016-12-23", 
 
    }, { 
 
     "data": "some data5", 
 
     "user": "B", 
 
     "createdAt": "2016-12-25", 
 
    }, { 
 
     "data": "some data6", 
 
     "user": "C", 
 
     "createdAt": "2016-12-24", 
 
    }], 
 
    sorted = _.orderBy(
 
     data, 
 
     ['user', function(d) { 
 
     return new Date(d.createdAt) 
 
     }], 
 
     ['asc', 'desc'] // 'desc' orders by date descending 
 
    ), 
 
    uniqued = _.uniqBy(sorted, 'user'); 
 

 
console.log(uniqued);

1

с простым JavaScript, вы можете сделать это, как это

var myArray = [ 
 
    { 
 
      "data": "some data", 
 
      "user": "A", 
 
      "createdAt":"2016-12-24", 
 
    }, 
 
    { 
 
      "data": "some data2", 
 
      "user": "B", 
 
      "createdAt":"2016-12-24", 
 
    }, 
 
    { 
 
      "data": "some data3", 
 
      "user": "A", 
 
      "createdAt":"2016-12-25", 
 
    }, 
 
    { 
 
      "data": "some data4", 
 
      "user": "A", 
 
      "createdAt":"2016-12-23", 
 
    }, 
 
    { 
 
      "data": "some data5", 
 
      "user": "B", 
 
      "createdAt":"2016-12-25", 
 
    }, 
 
    { 
 
      "data": "some data6", 
 
      "user": "C", 
 
      "createdAt":"2016-12-24", 
 
    }, 
 
] 
 

 

 

 
function getLatestItems(itemArray) { 
 
    var latestItemPerUser = {}, latesItems = [], newDate, oldDate; 
 

 
    for(var i = 0, l = itemArray.length; i < l; ++i) { 
 
     if(!latestItemPerUser[itemArray[i].user]) { 
 
      latestItemPerUser[itemArray[i].user] = itemArray[i]; 
 
     } else { 
 
      newDate = new Date(itemArray[i].createdAt); 
 
      oldDate = new Date(latestItemPerUser[itemArray[i].user].createdAt); 
 

 
      if(oldDate < newDate) { 
 
       latestItemPerUser[itemArray[i].user] = itemArray[i]; 
 
      } 
 
     } 
 
    } 
 

 
    for(var item in latestItemPerUser) { 
 
     latesItems.push(latestItemPerUser[item]); 
 
    } 
 

 
    return latesItems; 
 
} 
 

 
console.log(getLatestItems(myArray));

+0

Хорошее решение для чистого JavaScript. Приоритет для тех, кто приезжает сюда в будущем и ищет способ сделать это без дополнительных библиотек. Метод 'sort()' в [прототипе расширения] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) на javascript (встроен в большинство браузеров сейчас), может ускорить метод сортировки по ключу, делая это, возможно, быстрее. –

+0

Спасибо, @SamuelJackson. С другой стороны, мы могли бы избавиться от объекта Date, если мы уверены, что свойство «createdAt» всегда имеет формат «YYYY-MM-DD». Кроме того, если мы сможем использовать ES2015, код будет выглядеть как –

+0

' Функция getLatestItemsES6 (itemArray) { let lastItems = []; for (var item itemArray.sort ((a, b) => a.createdAt obj.user === item.user)) { lastItems.push (item); } } return latestItems; } ' –

2

Другим решением в простом Javascript с хэш-таблицей и чек на позже createdAt.

var data = [{ "data": "some data", "user": "A", "createdAt": "2016-12-24", }, { "data": "some data2", "user": "B", "createdAt": "2016-12-24", }, { "data": "some data3", "user": "A", "createdAt": "2016-12-25", }, { "data": "some data4", "user": "A", "createdAt": "2016-12-23", }, { "data": "some data5", "user": "B", "createdAt": "2016-12-25", }, { "data": "some data6", "user": "C", "createdAt": "2016-12-24", }], 
 
    result = data.reduce(function (hash) { 
 
     return function (r, a) { 
 
      if (!(a.user in hash)) { 
 
       hash[a.user] = r.push(a) - 1; 
 
       return r; 
 
      } 
 
      if (r[hash[a.user]].createdAt < a.createdAt) { 
 
       r[hash[a.user]] = a; 
 
      } 
 
      return r; 
 
     }; 
 
    }(Object.create(null)), []); 
 

 
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

+0

Первый раз, когда я натолкнулся на код, я не понимаю полностью, что работает И это хороший чистый код. Из того, что я вижу, на уровне скрипта нет реального цикла - это похоже на эквивалент LINQ, но на JavaScript? все данные передаются методу через 'reduce', и метод действует рекурсивно? –

+0

@SamuelJackson, в основном он использует закрытие над 'hash' и обратный вызов, который вызывается для каждого элемента' data', и это представлено 'a' в обратном вызове. результат собирается в 'r' и возвращается для каждого цикла. в то время как обратный вызов вызывается для каждого элемента, это не рекурсивный вызов, потому что он не вызывает себя. –

+0

Очень сексуальная часть javascript. Спасибо за информацию.По рекурсии я имел в виду, что он передает данные этому методу для каждого элемента в массиве и возвращает результаты. Таким образом, он похож на LINQ .NET. Я люблю его <3 –