Сравните два массива объектов и отфильтруйте несоответствия, чтобы создать новый массив

#javascript #node.js #arrays #compare #put

Вопрос:

Я исполняю два GET requests . Один в мою базу данных, а другой из API.

У меня есть два массива объектов. В массиве из моей базы данных он будет содержать данные игроков с некоторыми из их «Активных» статусов, установленных в true или false (я создаю функцию на переднем конце своего приложения, которая позволяет пользователю контролировать, активен ли кто-то или нет). В массиве из API он также будет содержать данные игроков, но ВСЕ их «Активные» статусы установлены true по умолчанию, и эти данные извлекаются каждые 24 часа и отправляются в мою базу данных через a PUT request и перезаписывают все данные.

Цель: Если для статуса «Активный» в массиве из базы данных установлено значение false, я хочу игнорировать эти объекты в массиве из API и обновлять базу данных только 'Active': true игроками.

Вот пример того, что было бы в моей базе данных:

 [{
    "PlayerID": 12345,
    "Team": "ABC",
    "FirstName": "Patrick",
    "LastName": "Star",
    "Position": "RB",
    "Active": false,
    "__v": 0
},
{
    "PlayerID": 67890,
    "Team": "DEF",
    "FirstName": "Spongebob",
    "LastName": "Squarepants",
    "Position": "WR",
    "Active": true,
    "__v": 0
}]
 

Вот пример из API. Обратите внимание, что «Активный» статус Патрика Стара соответствует действительности:

 [{
    "PlayerID": 12345,
    "Team": "ABC",
    "FirstName": "Patrick",
    "LastName": "Star",
    "Position": "RB",
    "Active": true,
    "__v": 0
},
{
    "PlayerID": 67890,
    "Team": "DEF",
    "FirstName": "Spongebob",
    "LastName": "Squarepants",
    "Position": "WR",
    "Active": true,
    "__v": 0
}]
 

Я хочу сравнить эти два массива и вернуть новый массив с активными игроками (в данном случае Губка Боб Квадратные штаны). Таким образом, игроки 'Active': false , которые находятся, не затрагиваются в базе данных. Я подумал, что могу использовать «Идентификатор игрока» в качестве ссылки, чтобы помочь определить, какие игроки активны или нет, и отфильтровать их оттуда. Но я застрял — любая помощь приветствуется!

РЕДАКТИРОВАТЬ — Вот моя функция, которая должна быть реализована в:

 function getPlayers() {
  const APIplayersURL = "someURL";
  const DBoffensivePlayersURL = "http://localhost:4000/api/offensiveplayers";

  axios.get(DBoffensivePlayersURL).then((res) => {
    const inactivePlayers = res.data;

    // Filter out all of the active players
    const dbArr = inactivePlayers.filter(
      players =>
        players.Active === false
    );
    
    axios.get(APIplayersURL).then((res) => {
      const players = res.data;

      // Filter out all players except for QB, RB and WR
      const offensivePlayers = players.filter(
        players =>
          players.Position === "QB" ||
          players.Position === "RB" ||
          players.Position === "WR"
      );
      
      // Give me all active QBs, RBs, and WRs
      const apiArr = offensivePlayers.filter(
        offensivePlayers =>
          offensivePlayers.Status === "Active"
      );
  
      const result = dbArr.filter(
        (obj) => obj.Active amp;amp; apiArr.some((o) => o.PlayerID === obj.PlayerID)
      );
      
      console.log(result);

      const config = {
        headers: {
          "Content-Type": "application/json",
          "Authorization": "x-auth-token",
          "Access-Control-Allow-Origin": "*"
        },
      };
  
        axios
          .put("http://localhost:4000/api/offensiveplayers", result, config)
          .then((res) => console.log(res))
          .catch((err) => console.error(err));
        console.log("Players updated successfully");
      });
  });
}

// Runs the getPlayers every 24 hours
setInterval(getPlayers, 86400000);
 

Ответ №1:

Вы можете использовать фильтр здесь, чтобы отфильтровать объекты, которые существуют apiArr , и один и тот же объект со PlayerID Active статусом true

 dbArr.filter((obj) => obj.Active amp;amp; apiArr.some((o) => o.PlayerID === obj.PlayerID));
 
 const dbArr = [
  {
    PlayerID: 12345,
    Team: "ABC",
    FirstName: "Patrick",
    LastName: "Star",
    Position: "RB",
    Active: false,
    __v: 0,
  },
  {
    PlayerID: 67890,
    Team: "DEF",
    FirstName: "Spongebob",
    LastName: "Squarepants",
    Position: "WR",
    Active: true,
    __v: 0,
  },
];

const apiArr = [
  {
    PlayerID: 12345,
    Team: "ABC",
    FirstName: "Patrick",
    LastName: "Star",
    Position: "RB",
    Active: true,
    __v: 0,
  },
  {
    PlayerID: 67890,
    Team: "DEF",
    FirstName: "Spongebob",
    LastName: "Squarepants",
    Position: "WR",
    Active: true,
    __v: 0,
  },
];

const result = dbArr.filter(
  (obj) => obj.Active amp;amp; apiArr.some((o) => o.PlayerID === obj.PlayerID)
);


console.log(result); 

Комментарии:

1. Вы могли бы ускорить выполнение, воспользовавшись коротким замыканием в состоянии фильтра, так как нет причин делать .some , если obj.Active значение false.

2. Мне это и в голову не приходило. Это прекрасная часть оптимизации. Спасибо за предложение @StevenB.

3. @decpk Огромное спасибо за ответ! Поэтому я внедрил это в свой код, но он возвращает пустой массив :/ Я отредактировал свой вопрос, чтобы включить свою функцию. Возможно, вы видите, чего мне не хватает.

Ответ №2:

Используйте метод фильтра для удаления объектов/значений, которые не возвращают значение true.

 const players = [{
    PlayerID: 12345,
    Team: "ABC",
    FirstName: "Patrick",
    LastName: "Star",
    Position: "RB",
    Active: false,
    __v: 0
},
{
    PlayerID: 67890,
    Team: "DEF",
    FirstName: "Spongebob",
    LastName: "Squarepants",
    Position: "WR",
    Active: true,
    __v: 0
}];

const online = players.filter(player => player?.Active);

console.log(online); 

Теперь, если вы хотите, чтобы ignore пользователи, которые находятся в автономном режиме в БД, вы также можете использовать идентификатор для проверки.

 const playersDB = [{
    PlayerID: 12345,
    Team: "ABC",
    FirstName: "Patrick",
    LastName: "Star",
    Position: "RB",
    Active: false,
    __v: 0
  },
  {
    PlayerID: 67890,
    Team: "DEF",
    FirstName: "Spongebob",
    LastName: "Squarepants",
    Position: "WR",
    Active: true,
    __v: 0
  }
];

const playersAPI = [{
    PlayerID: 12345,
    Team: "ABC",
    FirstName: "Patrick",
    LastName: "Star",
    Position: "RB",
    Active: true,
    __v: 0
  },
  {
    PlayerID: 67890,
    Team: "DEF",
    FirstName: "Spongebob",
    LastName: "Squarepants",
    Position: "WR",
    Active: true,
    __v: 0
  }
];

const online = playersAPI.filter(player => {
  const copy = playersDB.filter(p => p.PlayerID == player.PlayerID);
  if(!copy.length) return false;
  return copy[0].Active;
})
console.log(online) 

Комментарии:

1. Это будет фильтровать только объекты , чей Active статус есть true , но вы не проверяете, существует ли он также в массиве, который исходит из API