1

I am using vanilla js for this helper function inside of a react app / typescript. Json data is fetched this holds every letter of the alphabet which is assigned a value and a key. These are layed out into a grid of tiles. When a user selects a tile, this is added to gameData array in React which is used for a list. If a user clicks onto the same tile this is merged so instead of multiple list elements with same values they are merged with quantity + quantity and value + value

The structure is as such

const apiData = [
  {key: 'A', value: 50, quantity: 1, color: '#3498db', ...etc},
  {key: 'B', value: 40, quantity: 1, color: '#e67e22', ...etc},
  ...
]

const gameData = [
 {key: 'A', value: 200, quantity: 4, color: '#3498db', ...etc},
 {key: 'E', value: 10, color: '#fa0', ...etc},
]

export function groupBy(array: GameData[]) {
  const group: GameData[] = Object.values(
    array.reduce((acc: any, { value, quantity, ...r }) => {
      const key = Object.entries(r).join("-");
      acc[key] = acc[key] || { ...r, quantity: 0, value: 0 };
      return ((acc[key].value += value), (acc[key].quantity += 1)), acc;
    }, {})
  );
  return group;
}

The reducer works and merges properly but I just feel like there must be a better way to do this. Any ideas?

3
  • 2
    That looks just fine to me, linting aside. I'd prefer to use for..of instead of reduce, but using the same basic principle. Commented Apr 19, 2020 at 11:55
  • Do you want to game data to be grouped with the same and add the total value? Commented Apr 19, 2020 at 11:57
  • @AadilMehraj I edited it to show what the data looks like when merged with function Commented Apr 19, 2020 at 12:12

2 Answers 2

2

You can clean your groupBy reduce function as follows:

function groupBy(data: GameData[]) {
    const result = data.reduce((total, item) => {
          const { key, value, quantity } =   item;
          const prevItem = total[key] || {};
          const {value: prevValue = 0, quantity: prevQuantity = 0} = prevItem;


          total[key]= {
                ...item,
                value: prevValue + value,
                quantity: prevQuantity + quantity,
          };

          return total;

    }, {});

    return Object.values(result);
}

For the given input it produces the folowing result:

const gameData = [
  {"key":"A","value":50,"quantity":1,"color":"#3498db"},
  {"key":"A","value":50,"quantity":1,"color":"#3498db"},
  {"key":"A","value":50,"quantity":1,"color":"#3498db"},
  {"key":"B","value":50,"quantity":1,"color":"#3498db"},
  {"key":"B","value":40,"quantity":1,"color":"#e67e22"}
];

const result = groupBy(gameData);
/*
result = [
  {"key":"A","value":150,"quantity":3,"color":"#3498db"},
  {"key":"B","value":90,"quantity":2,"color":"#e67e22"}
]
*/
Sign up to request clarification or add additional context in comments.

Comments

1

Your solution seems ok, just a little hard to read. Here are my suggestions.

function groupBy(array){
    return Object.values(array.reduce((grouped, {value, quantity,...rest}) => {
        const key = Object.entries(rest).join('-');
        if(!grouped[key]){
            grouped[key] = {...rest, value: 0, quantity: 0};
        }
        grouped[key].quantity++;
        grouped[key].value += value;
        return grouped;
    },{}));
}

Or using a simple for:

function groupBy(array) {
    const grouped = {};
    for(let obj of array){
        const {value, quantity, ...rest} = obj;
        const key = Object.entries(rest).join('-');
        if(!grouped[key]){
            grouped[key]= {...rest, value: 0, quantity: 0};
        }
        grouped[key].quantity++;
        grouped[key].value+=value;
    }
    return Object.values(grouped);
}

1 Comment

Remember to use const when you aren't going to reassign - let is a warning to other readers of the code that you may reassign the identifier on the future

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.