Home > Blockchain >  Group set of objects based on a string value and edit
Group set of objects based on a string value and edit

Time:01-16

I have a array of objects like this

const resultSet = [
    {
        start: 'A',
        end: 'B',
        val: 1

    },
    {
        start: 'B',
        end: 'C',
        val: 3
    },
    {
        start: 'B',
        end: 'D',
        val: 1

    },
    {
        start: 'B',
        end: 'A',
        val: 4
    },
    {
        start: 'C',
        end: 'B',
        val: 1
    }
]

For the objects which have the same start and end (also in reverse order), the val should be updated with the maximum value among val. For instance, the first object and the fourth object in the array should have the same val as 4 since it is the max(1,4).

The final result should look like this

const finalSet = [
    {
        start: 'A',
        end: 'B',
        val: 4

    },
    {
        start: 'B',
        end: 'C',
        val: 3
    },
    {
        start: 'B',
        end: 'D',
        val: 1

    },
    {
        start: 'B',
        end: 'A',
        val: 4
    },
    {
        start: 'C',
        end: 'B',
        val: 3
    }
]

I started with the following

const strArray = resultSet.map(element => {
    return {
        str: [element.start, element.end].sort().join(''),
        val: element.val
    }
})

console.log(strArray)

I did end up with a array of objects

[
  { str: 'AB', val: 1 },
  { str: 'BC', val: 3 },
  { str: 'BD', val: 1 },
  { str: 'AB', val: 4 },
  { str: 'BC', val: 1 }
]

My idea is to somehow group this result based on the value of str and use Max function on the group to update val to the max value. Is there a efficient way to do this?

In case there is a better approach than what I was trying, please let me know too.

CodePudding user response:

You could take an object with normalized key and max value and map the data with max values.

const
    getKey = ({ start, end }) => [start, end].sort().join('|'),
    data = [{ start: 'A', end: 'B', val: 1  }, { start: 'B', end: 'C', val: 3 }, { start: 'B', end: 'D', val: 1 }, { start: 'B', end: 'A', val: 4 }, { start: 'C', end: 'B', val: 1 }],
    max = data.reduce((m, o) => {
        const key = getKey(o);
        if (!(key in m) || m[key] < o.val) m[key] = o.val;
        return m;
    }, {}),
    result = data.map(o => ({ ...o, val: max[getKey(o)] }));

console.log(result);
console.log(max);
.as-console-wrapper { max-height: 100% !important; top: 0; }

CodePudding user response:

You could first make an object with all the highest values. Afterwards loop over your array and apply the correct values.

const finalSet = [
    { start: 'A', end: 'B', val: 4 },
    { start: 'B', end: 'C', val: 3 },
    { start: 'B', end: 'D', val: 1 },
    { start: 'B', end: 'A', val: 4 },
    { start: 'C', end: 'B', val: 3 }
];

/**
 * Get key based on `start` and `end` props.
 */
const getKey = obj => [obj.start, obj.end].sort().join(''); // Might be better to use `localeCompare` for sorting strings.

/**
 * Get highest value based on key.
 */
const highestValues = finalSet.reduce((acc, obj) => {
  const key = getKey(obj);
  acc[key] ??= 0;
  
  if(obj.val > acc[key]) {
    acc[key] = obj.val;
  }
  
  return acc;
}, {});

/**
 * Update initial values with highest value.
 */
const result = finalSet.map(obj => {
  const key = getKey(obj);
  obj.val = highestValues[key];
  return obj;
});

console.log(result);

CodePudding user response:

Probably the easiest solution will be to iterate over the array, find all matching entries, map them to values and find max. Then just update val property.

list.forEach(o1 => {
     const arr = list.filter( o2 => (o2.start === o1.start && o1.end === o2.end) || (o2.start === o1.end && o2.end === o1.start) )
                     .map(o2 => o2.val);
    o1.val = Math.max(...arr);
});
  • Related