У меня есть два набора данных разной длины. Мне нужно перебрать оба массива и вставить URL-адрес фотографии соответствующего идентификатора игрока в новый массив. Я делаю это после, данные API загружены в мой компонент React, поэтому, похоже, это не связано с тем, что данные еще не загружены. Я могу console.info обоих наборов данных и видеть, что они успешно возвращаются из API. Все это работает в JS Fiddle (ссылка ниже), но не в React. Так что мне сложно отследить, что происходит.
Вот мои наборы данных (все они явно сокращены):
Этот массив объектов возвращается из конечной точки API, которая содержит всю информацию о плеере, такую как идентификатор, URL-адреса фотографий и т. д. (Это более 1200 объектов):
playerInfo = [
{PlayerID: 123, PhotoURL: url123},
{PlayerID: 345, PhotoURL: url345},
{PlayerID: 678, PhotoURL: url678},
{PlayerID: 910, PhotoURL: url910},
{PlayerID: 1112, PhotoURL: "url1112"},
{PlayerID: 1213, PhotoURL: "url1213"}
];
Эти данные возвращаются из отдельной конечной точки API, в которой перечислены текущие лидеры (возвращаются 40 лучших лидеров):
playerIDs = [123, 345, 678, 910]
К сожалению, эти данные таблицы лидеров не включают URL-адреса фотографий с возвращенными идентификаторами игроков, поэтому мне нужно сравнить идентификаторы игроков в обоих массивах, а затем нажать PhotoURL из указанного выше соответствующего массива playerInfo.
Мой подход заключается в следующем (я, вероятно, мог бы использовать для этого какую-то функцию ES6, поэтому, пожалуйста, дайте мне знать, если это так.):
let leaderPhotos = [];
for(let i = 0; i < playerInfo.length; i++) {
if (playerInfo[i].PlayerID === playerIDs[i]) {
leaderPhotos.push(playerInfo[i].PhotoURL);
}
}
Я считаю, что даже несмотря на то, что массив playerIDs короче, чем массив PlayerInfo, установка цикла на длину массива PlayerInfo позволит сравнивать более короткий массив таблицы лидеров PlayerIDs с идентификатором каждого игрока в массиве объектов PlayerInfo, поскольку любой проигрыватель может быть в таблице лидеров в любой момент. Если идентификатор игрока совпадает в обоих массивах, он помещает значение URL-адреса фотографии объекта PlayerInfo в массив, который я затем могу использовать для загрузки в фотографии лучших лидеров. Поскольку цикл проходит через таблицу лидеров PlayerIDs, возвращенные URL-адреса фотографий располагаются в порядке таблицы лидеров.
Здесь он работает в JS Fiddle. Вы можете видеть в консоли, что он выталкивает только URL-адреса фотографий соответствующих идентификаторов игроков. Отлично, именно то, что я хочу.
Однако, когда то же самое применяется внутри компонента React, ответственного за обработку данных API, я получаю пустой массив в консоли после того, как логика выполнит его. Я могу console.info оба возвращенных набора данных API, чтобы убедиться, что я успешно возвращаю данные для работы.
Я возился и решил посмотреть, будет ли установка обоих индексов массива на значение работать так:
let leaderPhotos = [];
if (playerInfo[0].PlayerID === playerIDs[0]) {
leaderPhotos.push(playerInfo[0].PhotoURL);
} else {
return false;
} console.info(leaderPhotos);
И, конечно же, это подтолкнет URL-адрес подходящей пары к фотографии в leaderPhotos, как и ожидалось без в цикле for. Мне трудно понять, почему цикл for не работает, хотя в JS Fiddle он доказывает, что он должен возвращать желаемые результаты. Заранее благодарим за любые советы!



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Попробуй это
let leaderPhotos = playerInfo.filter(plr => playerIDs.indexOf(plr.PlayerID) !== -1).map( t => t.PhotoURL);
Убедитесь, что оба ваших массива имеют одинаковый порядок на основе playerId.
В противном случае нужно использовать две петли:
let leaderPhotos = [];
for(let i = 0; i < playerInfo.length; i++) {
for(let j = 0; j < playerIDs.length; j++ )
if (playerInfo[i].PlayerID === playerIDs[j]) {
leaderPhotos.push(playerInfo[i].PhotoURL);
}
}
Short clean version
const leaderPhotos = playerIDs.map(id =>
playerInfo.find(({ PlayerID }) => PlayerID === id).PhotoURL
);
Примечание. Чтобы вы знали, что это вложенный цикл. Где map - это петля, проходящая через доску лидеров, а find - это петля, проходящая через плееры. Временная сложность равна О (н * м), где
Though if the total number of users isn't huge it shouldn't matter and as long as the code looks clean and understandable that would always be better (:
Если у вас есть количество пользователей ОГРОМНЫЙ, и вы хотите иметь наибольшее количество кода эффективный. Что вам следует сделать, так это сохранить свой playerInfo в карте / объекте, где ключом является playerId, а значением - playerURL. Таким образом, ему нужно всего лишь один раз пройтись по вашим объектам и получить О (1) для фотографий игроков.
Efficient Version
const playerMap = {};
playerInfo.forEach((player) => {
playerMap[player.PlayerID] = player.PhotoURL;
});
const leaderPhotos = playerIDs.map(leaderId => playerMap[leaderId]);
Временная сложность этого составляет не более На), где
Ваше первое решение дает ошибку в JSFiddle. Не могли бы вы проверить код?
Ой! Спасибо! В основном я пытался сделать псевдокод и не видел JSFiddle
Это сработало для меня идеально. Я ценю объяснение.
Я думаю, что это самое короткое решение по сравнению с другими ответами:
let leaderPhotos = playerInfo.filter((info) => playerIDs.includes(info.PlayerID)).map(id => id.PhotoURL);
Не могли бы вы предоставить код вашего реагирующего компонента?