0

I need to filter out objects in array if specific key value is null.(trying to learn)

const getPlayerData = async () => {
  const allPlayers = await fetchData("https://api.sleeper.app/v1/players/nfl");
  const players = Object.keys(allPlayers).map(function(key) {
    return allPlayers[key]
  })

  const activePlayers = await Promise.all(players?.filter(async(player: any) => {player.search_rank !== null}
).sort((a, b) => a.search_rank - b.search_rank));
  
  console.log(activePlayers)
  return activePlayers;
}

it filters if {player.active = true} but i need to filter if player.search_rank is null aswell

9
  • Remove the braces around that expression.
    – trincot
    Commented Jan 4 at 8:43
  • "it filters if {player.active = true}": there is nothing in the code that you have presented that does that. There is not even an access to that property.
    – trincot
    Commented Jan 4 at 8:45
  • instead of player.search_rank !== null i filter with with player.active = true and it works as expected
    – D_chez12
    Commented Jan 4 at 9:00
  • removing brackets does not fix the issue
    – D_chez12
    Commented Jan 4 at 9:01
  • I think const players = Object.values(allPlayers) would be way better than what you did there... Then you just need to const activePlayers = players.filter(player => player.active && (player.search_rank !== null)). Then you can populate another variable like const rankedActivePlayers = activePlayers.sort(...). Also, I think your .sort(...) callback should be different, like (a, b) => a.search_rank == b.search_rank ? 0 : a.search_rank > b.search_rank ? 1 : -1. This way, if a.search_rank is greater than b.search_rank then b will come first.
    – KLASANGUI
    Commented Jan 4 at 9:02

2 Answers 2

3

I've modified the above code assuming that fetchData function will get the data from API. Please ignore the implementation of fetchData.

const fetchData = async (url) => {
    return await fetch(url).then(res => res.json())
}

const getPlayerData = async () => {
  const allPlayers = await fetchData("https://api.sleeper.app/v1/players/nfl");
  const players = Object.keys(allPlayers).map((key) => allPlayers[key]);

  const activePlayers = players
          ?.filter((player) => player.search_rank !== null) 
          .sort((a, b) => a.search_rank - b.search_rank);
  
  console.log(activePlayers)
  return activePlayers;
}

Changes made:

  • Modified line which contains const players to use arrow function and return it without explicitly writing return statement. --- You may ignore this change.
  • Removed unnecessary Promise.all as the data is already received and we are applying filter and sort functions which are synchronous operations. async is also not required inside the filter callback as we are not performing any asynchronous operations inside filter function.

The main issue is we have to return player.search_rank !== null which is present inside filter function or write it as arrow function without brackets {}.

1
  • 1
    Sure, let me update in the answer
    – Dinesh
    Commented Jan 4 at 9:30
0

Friend, I did some major changes to your function and now it works just fine.

const fetchData = async ( url ) => await (await fetch(url)).json();

const getPlayerData = async () =>
{
  // Gets all enumerable values directly as an array.
  const players = Object.values
  (
    await fetchData("https://api.sleeper.app/v1/players/nfl")
  );
  
  const rankedPlayers = players
    .filter
    (
      // Filters if a player is active and has a rank (not undefined or null).
      player => ( player.active && (player.search_rank != null) )
    )
    .sort
    (
      // Sorts the players by `search_rank` only.
      ( a, b ) => a.search_rank - b.search_rank
    );
  
  return rankedPlayers;
}

console.clear();
console.log('Fetching data...');
getPlayerData().then
(
  rankedPlayers => console.log
  ({
    'Number of ranked players': rankedPlayers.length,
    'First in the list':
    {
      'Parsed full name': rankedPlayers.at(0).first_name + ' ' + rankedPlayers.at(0).last_name,
      'Search rank': rankedPlayers.at(0).search_rank,
    },
    'Second in the list':
    {
      'Parsed full name': rankedPlayers.at(1).first_name + ' ' + rankedPlayers.at(1).last_name,
      'Search rank': rankedPlayers.at(1).search_rank,
    },
    'Third in the list':
    {
      'Parsed full name': rankedPlayers.at(2).first_name + ' ' + rankedPlayers.at(2).last_name,
      'Search rank': rankedPlayers.at(2).search_rank,
    },
  })
);
.as-console-wrapper { min-height: 100%; }

PS.: I noticed that the data contains non-unique search_rank values. So, it maybe is better to change the .sort() callback function to fit all criteria for the desired sorting... Like, if there's two search_rank with the same value, which should be sorted first then? In the current example they'll stay in place (so, the first as sorted in the raw data comes first).

By the way, it's possible to make it a one-liner:

// One-liner:
const getPlayerData = async () => Object.values(await (await fetch("https://api.sleeper.app/v1/players/nfl")).json()).filter(player => ( player.active && (player.search_rank != null) )).sort(( a, b ) => a.search_rank - b.search_rank);

// TEST:
console.clear();
console.log('Fetching data...');

getPlayerData().then
(
  rankedPlayers => console.log
  ({
    'Ranked Players': rankedPlayers.length,
    'First Player': rankedPlayers.at(0),
  })
);

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.