javascript - JS: Don't add value to map on condition - Stack Overflow

I have an object that I need to convert into an array. This is the object:const dogCounts: {maltese: 4

I have an object that I need to convert into an array. This is the object:

const dogCounts: {
    maltese: 4,
    poodle: 2,
    labrador: 10,
    corso: 0
}

And I send it to a ponent thru props and I have a useMemo hook to convert it into a structure like this: [ [maltese, 4], [poodle, 2], ... ]

const formatDogCounts = useMemo(() => {
    const z = Object.keys(dogCounts || {})?.map(i => {
        if (dogCounts[i] === 0) return; // Don't add it to map and skip it

        return [i, dogCounts[i]]
    })
}, [dogCounts])

When the number is zero I don't want to add it to the formatDogCounts variable. What I put above doesn't fit to eslints rules. Arrow function expected no return value.eslintconsistent-return.

Also I put that {} in the object.keys for the case when the counts haven't loaded yet is there a cleaner way to null check that?

I have an object that I need to convert into an array. This is the object:

const dogCounts: {
    maltese: 4,
    poodle: 2,
    labrador: 10,
    corso: 0
}

And I send it to a ponent thru props and I have a useMemo hook to convert it into a structure like this: [ [maltese, 4], [poodle, 2], ... ]

const formatDogCounts = useMemo(() => {
    const z = Object.keys(dogCounts || {})?.map(i => {
        if (dogCounts[i] === 0) return; // Don't add it to map and skip it

        return [i, dogCounts[i]]
    })
}, [dogCounts])

When the number is zero I don't want to add it to the formatDogCounts variable. What I put above doesn't fit to eslints rules. Arrow function expected no return value.eslintconsistent-return.

Also I put that {} in the object.keys for the case when the counts haven't loaded yet is there a cleaner way to null check that?

Share Improve this question edited Feb 9, 2021 at 17:45 Seth McClaine 10.1k7 gold badges42 silver badges67 bronze badges asked Feb 9, 2021 at 17:27 ousmane784ousmane784 4661 gold badge11 silver badges22 bronze badges 1
  • map includes every item, nevertheless the return value. Use filter instead of map. – Teemu Commented Feb 9, 2021 at 17:30
Add a ment  | 

3 Answers 3

Reset to default 6

map doesn't filter out values; doing a simple return; in map makes the corresponding entry in the result array undefined. If you want to do that, you'll need to filter first, or build the array another way (such as a simple loop).

Here's the filter approach:

const formatDogCounts = useMemo(() => {
    const z = Object.keys(dogCounts || {})?
                .filter(name => dogCounts[name] !== 0)
                .map(name => [name, dogCounts[i]]);
}, [dogCounts]);

Note that Object.entries provides the very [name, value] pairs you want, so you could avoid map, and there's no reason for the conditional chaining operator as neither Object.keys nor Object.entries ever returns undefined or null:

const formatDogCounts = useMemo(() => {
    const z = Object.entries(dogCounts || {})
                .filter(([, value]) => value !== 0);
}, [dogCounts]);

Note the , prior to value in the [, value] destructuring pattern so we're grabbing the second array entry (the value), not the first (the name).

We can also avoid the calls to Object.entries and filter entirely when there is no dogCounts:

const formatDogCounts = useMemo(() => {
    const z = dogCounts
        ? Object.entries(dogCounts).filter(([, value]) => value !== 0)
        : [];
}, [dogCounts]);

In a ment you've said:

The entries solution worked really well for me! Is there a way now to return an object instead of an array with total dog counts and then an array of items? Ex: formatDogCounts: { totalDogs: 30, items: [...] }

Sure. If there will only ever be a reasonable number of dogs (fewer than hundreds of thousands), I'd just do it as a separate operation at the end:

const formatDogCounts = useMemo(() => {
    const items = dogCounts
        ? Object.entries(dogCounts).filter(([, value]) => value !== 0)
        : [];
    return {
        totalDogs: items.reduce((sum, [, value]) => sum + value, 0),
        items,
    };
}, [dogCounts]);

(A straight sum is the only ad hoc use of reduce I'll do, and even then I don't much care for it.)

Or you could make your filter callback slightly impure and count them as you go:

const formatDogCounts = useMemo(() => {
    let totalDogs = 0;
    const items = dogCounts
        ? Object.entries(dogCounts).filter(([, value]) => {
            totalDogs += value;
            return value !== 0;
        })
        : [];
    return {
        totalDogs,
        items,
    };
}, [dogCounts]);

If you want to perform a map and filter operation together, you can use flatMap, returning an empty array to skip an element.

const formatDogCounts = useMemo(() => {
    const z = Object.keys(dogCounts || {})?.flatMap(i => {
      if(dogCounts[i] === 0) return []; // Dont add it to map and skip it

      return [[i, dogCounts[i]]];
    })
  }, [dogCounts])

You are trying to filter using a map which isn't possible. Map will return the same amount of values as you put in. You can do a foreach or you can do a bination of map and filter to get the expected results.

Foreach

const z = []

Object.keys(dogCounts).forEach((key) => {
  if(dogCounts[key]) {
    // if the value is truthy push the structure to the array. 
    z.push([key, dogCounts[key]]); 
  }
}

Map/Filter

const z = Object.keys(dogCount)
  .map((key) => [key, dogCount[key]) // map to restructure object.keys
  .filter(([key, value]) => value); // filter to remove falsey values (0, null, undefined) 

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745122534a4612497.html

相关推荐

  • javascript - JS: Don't add value to map on condition - Stack Overflow

    I have an object that I need to convert into an array. This is the object:const dogCounts: {maltese: 4

    6小时前
    20

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信