1

I have a function inside of a react class component which generates properties. Since I want to be able to have duplicate properties, I've done it in a way that it is possible. However, I want those duplicate properties to be combined as a single value so that it can be displayed in the render function as a single property with a bigger value instead of 2 properties with smaller values. How can I achieve this based on the below code?

changePropertyState = () => {
  let rngProperties = []

  let maxProp = this.state.rarity.maxProperties;
  let minProp = this.state.rarity.minProperties;

  let rngCurrentPropAmount = Math.floor(Math.random() * (maxProp - minProp + 1) + minProp);

  // the actual properties for an item based on the array of properties
  for (let i = 0; i < rngCurrentPropAmount; i++) {
    let rngNum = Math.floor(Math.random() * (itemProperties.length))
    rngProperties.push(itemProperties[rngNum])
  }


  let proxyProperties = []

  // setting the values for each property based on the min and max of that property
  for (let j = 0; j < rngProperties.length; j++) {
    let rngValue = this.getRandomNumber(rngProperties[j].min, rngProperties[j].max);
    rngProperties[j].value = rngValue;
  
    // creating a proxy to store unique values for each property,
    let obj = {
      id: rngProperties[j].id,
      name: rngProperties[j].name,
      min: rngProperties[j].min,
      max: rngProperties[j].max,
      value: rngProperties[j].value
    }
    proxyProperties.push(obj);
  }

  //setState() has an inbuilt functionality for a callback function, in which we can console.log the newly changed state
  this.setState({
    properties: proxyProperties
  }, () => {
    // console.log('propF', this.state)
  });
}

An expected output of the above code is the below picture. enter image description here

What I want to do is combine the 2 properties called (in this case) "Area Damage" so that only 1 property is listed but the value is 25 (again, in this case).

The itemProperties is an array of objects that have the following structure:

id: 1,
name: "intelligence",
min: 1,
max: 10,
value: 0

The rngCurrentPropAmount can be replaced with any integer for testing purposes. This is the amount of properties to be added.

1 Answer 1

1

The logic is to first group the array by name then merge them using reduce & summing the value. Bit tricky but working. Hope this is what was needed. The initial array has 4 elements & the final one has two. value is summed up.

const arr = [
  {
    id: 1, name: "intelligence", min: 1, max: 10, value: 11
  },
  {
    id: 1, name: "intelligence", min: 1, max: 10, value: 4
  },
  {
    id: 2, name: "dexterity", min: 1, max: 10, value: 3
  },
  {
    id: 2, name: "dexterity", min: 1, max: 10, value: 8
  }
];

//group an array by property 
function groupBy(arr, property) {
  return arr.reduce(function(memo, x) {
    if (!memo[x[property]]) {
      memo[x[property]] = [];
    }
    memo[x[property]].push(x);
    return memo;
  }, {});
}

//group by name
const grouped = groupBy(arr, "name");
const keys = Object.keys(grouped);
var output = [];

//loop keys
keys.forEach(key => {
  //merge using reduce
  const out = grouped[key].reduce((acc, current) => {
    return {
      id: current.id,
      name: current.name,
      min: current.min,
      max: current.max,
      value: acc.value + current.value
    }
  });
  output.push(out);
});

console.log(output);

Sign up to request clarification or add additional context in comments.

2 Comments

I used your code and it worked perfectly. Thank you for the quick response. If it is not too much trouble, could you please explain a bit more about the groupBy function that you built? I tried using reduce before I posted here, but couldn't make it work, but your solution is exactly what I needed. You also seem to use it in the keys.forEach section of the code. I can't wrap my head around it.
@inerpiece The groupBy is similar to lodash.com/docs/4.17.15#groupBy

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.