skip to Main Content

I have an array of objcets. With reduce method after looping i want to receive two seperate arrays. Now, i am doing this way.

const dogs = [
  { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] },
  { weight: 8, curFood: 200, owners: ['Matilda'] },
  { weight: 13, curFood: 275, owners: ['Sarah', 'John'] },
  { weight: 32, curFood: 340, owners: ['Michael'] },
];

So, with the below reduce methods i am receiving the result that i want (2 array).

const ownersEatTooMuch = dogs.reduce(function (acc, dog) {
  if (dog.curFood > dog.recommended * 1.1) {
    acc.push(dog.owners);
  }
  return acc.flat();
}, []);

const ownersEatTooLess = dogs.reduce(function (acc, dog) {
  if (dog.curFood < dog.recommended * 0.9) {
    acc.push(dog.owners);
  }
  return acc.flat();
}, []);

But is it possible to merge this into one reduce method to create 2 arrays. I imagine situation like this,

const [ownersEatTooMuch1, ownersEatTooLess1] = dogs.reduce(function (dog) {
  // When the condition will be true i want to fill first array ownersEatTooMuch1 and when another condition will be true i want to fill second array ownersEatTooLess1
}, [[], []]);
const [ownersEatTooMuch1, ownersEatTooLess1] = dogs.reduce(
  function (dog) {
    if (dog.curFood > dog.recommended * 1.1) {
      acc.push(dog.owners);
    }
  },
  [[], []]
);

I just don’t understand how to determine [[], [] between these and then push into ownersEatTooMuch1 or here ownersEatTooLess1

7

Answers


  1. I hope this is what you are looking for.
    Because your example code do not work (recommended undefined), and the output is not clear, im not sure if this is what you want.

    Based on the code you provided you want 2 arrays with "ate too much" or "ate too less".

    What about the cases which is neither "too much" or "too less"?
    See my comment in the array definition: does not apppear anywhere, neither "too much" or "too less"

    const dogs = [
        { weight: 22, curFood: 250, owners: ['Alice', 'Bob'], recommended: 10 },
        { weight: 8, curFood: 200, owners: ['Matilda'], recommended: 2000 },
        { weight: 13, curFood: 275, owners: ['Sarah', 'John'], recommended: 300 }, // does not apppear anywhere, neither "too much" or "too less"
        { weight: 32, curFood: 340, owners: ['Michael'], recommended: 1000 },
    ];
    
    
    
    const [ownersEatTooMuch, ownersEatTooLess] = dogs.reduce((arr, dog) => {
        
        if (dog.curFood > dog.recommended * 1.1) {
            arr[0].push(...dog.owners);
        }
    
        if (dog.curFood < dog.recommended * 0.9) {
            arr[1].push(...dog.owners);
        }
    
        return arr;
    
    }, [
        [], // too much
        []  // too less
    ]);
    
    
    console.log(ownersEatTooLess, ownersEatTooMuch)
    

    The reduce iteration returns every time the initial array passed to it, which is a 2 layer array.

    1. Item = Array for people "too much",
    2. Item = Array for people "too less".

    These arrays get then filled based on your calculation.

    The 2 layer array returned from reduce is then deconstructed into the variables ownersEatTooMuch & ownersEatTooLess.

    Login or Signup to reply.
  2. it’s easy. You can do something like that:

    const result = dogs.reduce((acc, curr)=> {      
     if (dog.curFood > dog.recommended * 1.1) {
        acc.a.push(dog.owners);
     } else {
        acc.b.push(dog.owners);
     }
    return acc
    }, 
    {
        a:[],
        b:[]
    }) 
    

    You should just update the result key to avoid duplication code ( i don’t know your specific logic)

        const result = dogs.reduce((acc, curr)=> {      
    let resultKey = 'default'
    
     //condition a
     if (dog.curFood > dog.recommended * 1.1) {
        resultKey = 'a'
     } else {
        resultKey = 'b'     
     } //...else if for any others keys...
         
     acc[resultKey].push(dog.owners);
    return acc
    }, 
    {
        default: [],
        a:[],
        b:[]
    }) 
    
    Login or Signup to reply.
  3. I think what you need is the ... (spread) operator.

    
    const dogs = [
      { weight: 22, curFood: 250, recommended: 224, owners: ['Alice', 'Bob'] },
      { weight: 8, curFood: 200,recommended: 300, owners: ['Matilda'] },
      { weight: 13, curFood: 275, recommended: 300, owners: ['Sarah', 'John'] },
      { weight: 32, curFood: 340, recommended: 300, owners: ['Michael'] },
    ];
    
    const [ownersEatTooMuch, ownersEatTooLess] = dogs.reduce(function (acc, dog) {
      const [ownersEatTooMuch, ownersEatTooLess] = acc;
      if (dog.curFood > dog.recommended * 1.1) {
        ownersEatTooMuch.push(...dog.owners);
      }else if(dog.curFood < dog.recommended * 0.9){
        ownersEatTooLess.push(...dog.owners);
      }
      return acc;
    }, [[], []]);
    
    
    
    Login or Signup to reply.
  4. Array push

    Array push with spread syntax

    You can use push with the spread syntax to add elements to each array:

    const dogs = [
      { weight: 22, curFood: 250, owners: ['Alice', 'Bob'], recommended: 200 },
      { weight: 8, curFood: 200, owners: ['Matilda'], recommended: 150 },
      { weight: 13, curFood: 275, owners: ['Sarah', 'John'], recommended: 350 },
      { weight: 32, curFood: 340, owners: ['Michael'], recommended: 400 },
    ];
    
    const [ownersEatTooMuch, ownersEatTooLess] = dogs.reduce(([a, b], dog) => {
        console.log(dog, a, b);
        if (dog.curFood > dog.recommended * 1.1) {
        a.push(...dog.owners);
      } else if (dog.curFood < dog.recommended * 0.9) {
        b.push(...dog.owners);
      }
      return [a, b];
    }, [[], []]);
    
    console.log(dogs);
    console.log('---');
    console.log(ownersEatTooMuch);
    console.log(ownersEatTooLess);
    

    Array push with Iteration

    You can use push and then iterate through the array of owners instead of using flat:

    const dogs = [
      { weight: 22, curFood: 250, owners: ['Alice', 'Bob'], recommended: 200 },
      { weight: 8, curFood: 200, owners: ['Matilda'], recommended: 150 },
      { weight: 13, curFood: 275, owners: ['Sarah', 'John'], recommended: 350 },
      { weight: 32, curFood: 340, owners: ['Michael'], recommended: 400 },
    ];
    
    const [ownersEatTooMuch, ownersEatTooLess] = dogs.reduce(([a, b], dog) => {
        console.log(dog, a, b);
        if (dog.curFood > dog.recommended * 1.1) {
        for (var owner of dog.owners) {
            a.push(owner);
        }
      } else if (dog.curFood < dog.recommended * 0.9) {
        for (var owner of dog.owners) {
            b.push(owner);
        }
      }
      return [a, b];
    }, [[], []]);
    
    console.log(dogs);
    console.log('---');
    console.log(ownersEatTooMuch);
    console.log(ownersEatTooLess);
    

    Array concat

    You can use reduce with the Array concat method to create two arrays, each iteration may create a new array since concat is not an in-place destructive operation:

    const dogs = [
      { weight: 22, curFood: 250, owners: ['Alice', 'Bob'], recommended: 200 },
      { weight: 8, curFood: 200, owners: ['Matilda'], recommended: 150 },
      { weight: 13, curFood: 275, owners: ['Sarah', 'John'], recommended: 350 },
      { weight: 32, curFood: 340, owners: ['Michael'], recommended: 400 },
    ];
    
    const [ownersEatTooMuch, ownersEatTooLess] = dogs.reduce(([a, b], dog) => {
        console.log(dog, a, b);
        if (dog.curFood > dog.recommended * 1.1) {
        return [a.concat(dog.owners), b];
      } else if (dog.curFood < dog.recommended * 0.9) {
        return [a, b.concat(dog.owners)];
      }
      return [a, b];
    }, [[], []]);
    
    console.log(dogs);
    console.log('---');
    console.log(ownersEatTooMuch);
    console.log(ownersEatTooLess);
    
    Login or Signup to reply.
  5. Sure:

    const dogs = [
      { weight: 22, curFood: 250, recommended: 200, owners: ['Alice', 'Bob'] },
      { weight: 8, curFood: 200, recommended: 250, owners: ['Matilda'] },
      { weight: 13, curFood: 275, recommended: 400, owners: ['Sarah', 'John'] },
      { weight: 32, curFood: 340, recommended: 340, owners: ['Michael'] },
    ];
    const {tooMuch, tooLess} = dogs.reduce(function (acc, dog) {
      if (dog.curFood > dog.recommended * 1.1) {
        acc.tooMuch = acc.tooMuch.concat(dog.owners);
      }
      else if (dog.curFood < dog.recommended * 0.9) {
        acc.tooLess = acc.tooLess.concat(dog.owners);
      }
      return acc;
    }, {tooMuch: [], tooLess: []});
    
    console.log(tooMuch);
    console.log(tooLess);

    Explanation:

    • we pass an object containing two empty arrays called tooMuch and tooLess
    • inside the function we do both comparisons
    • with else if, since we exclude someone eating too much and too less at the same time
    • if the criteria is fulfilled, then we concat the respective array with the owners at each step
    • returning acc
    • at the end, we destructure the resulting object into two constants, called tooMuch and tooLess, both being arrays
    • which then can be used further as normal constants and we console log them to illustrate this fact

    I have added a recommended field to each dog so the comparisons will make sense.

    Login or Signup to reply.
  6. Not the reduction you were asking for, but you could use one expression involving filter and flatMap:

    const dogs = [{ weight: 22, curFood: 250, recommended: 400, owners: ['Alice', 'Bob'] },
                  { weight: 8,  curFood: 200, recommended: 80,  owners: ['Matilda'] },
                  { weight: 13, curFood: 275, recommended: 130, owners: ['Sarah', 'John'] },
                  { weight: 32, curFood: 340, recommended: 500, owners: ['Michael'] }];
    
    const [ownersEatTooLess, ownersEatTooMuch] = [0.9, 1.1].map((factor, i) =>
        dogs.filter(dog => (dog.curFood >= dog.recommended * factor) == i)
            .flatMap(({owners}) => owners)
    );
    
    console.log({ownersEatTooMuch, ownersEatTooLess});

    This is not the fastest running code, but could be perceived as "elegant" (a matter of opinion).

    Note that it will deal differently when the ratio is exactly 1.1. In that case the owners will also be added in the "Too much" group. I assume this is not a problem. You can always adjust the factor to your liking.

    Secondly, the sloppy == is intended here. If you prefer using ===, then convert the left operand to number with a unary + operator.

    Login or Signup to reply.
  7. The reducer of this snippet delivers an array with 3* subarrays. The reducer result is spreaded into 3 variables.

    I had to guess the recommended value for the demo I used the function you gave in the comment section of your question to set recommended values.

    * Why 3? Because I guess there may be ‘undecided’ values, given the comparison you gave.

    const dogs = [
      { weight: 22, curFood: 250, owners: ['Alice', 'Bob'] },
      { weight: 8, curFood: 200, owners: ['Matilda'] },
      { weight: 13, curFood: 275, owners: ['Sarah', 'John'] },
      { weight: 32, curFood: 340, owners: ['Michael'] },
    ];
    
    setRecommendedPortions(dogs);
    
    const [under, over, undecided] = dogs
      .reduce((acc, { curFood, owners, recommended }) => {
        const accIndex = curFood < 0.9 * recommended 
          ? 0 : curFood > 1.1 * recommended ? 1 : 2;
        acc[accIndex] = acc[accIndex].concat(owners);
        return acc;
      }, [ [], [], [] ] );
    
    console.log(`under [${under}]`);
    console.log(`over  [${over}]`);
    console.log(`undecided (none of the above) [${undecided}]`);
    
    function setRecommendedPortions(dogs) {   
      dogs.forEach( d => d.recommended = Math.trunc(d.weight**0.75 * 28) );
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search