kubmin
kubmin

Reputation: 33

Removing duplicate objects in object array while keeping unique string values

Please bear with me, I'm a novice javascript developer with a sorting problem that I can't wrap my head around.

I'm retrieving an array of objects (JSON response) by an api like this:

var arr = [
    {
        "year": "2011",
        "activity": "bowling"
    },
    {
        "year": "2009",
        "activity": "shopping",
    },
    {
        "year": "2011",
        "activity": "cooking"
    },
    {
        "year": "2006",
        "activity": "singing"
    }
]

I have a function that removes all of the duplicate years (as intended), but I wish to take the 'activity' value of the duplicate object and add it to the activity value of that same year is left after removing duplicates

My function that removes the duplicate year is as follows

var new_arr = new_arr.reduce((unique, o) => {
  if(!unique.some(obj => obj.year === o.year)) {
    unique.push(o);
  }
  return unique;
},[]);

which leaves me with this

var arr = [
    {
        "year": "2011",
        "activity": "bowling"
    },
    {
        "year": "2009",
        "activity": "shopping",
    },
    {
        "year": "2006",
        "activity": "singing"
    }
]

What I wish to accomplish:

var arr = [
    {
        "year": "2011",
        "activity": "bowling, cooking"
    },
    {
        "year": "2009",
        "activity": "shopping",
    },
    {
        "year": "2006",
        "activity": "singing"
    }
]

JSFiddle: https://jsfiddle.net/4s1uaex0/2/

I feel like I'm almost there, but I don't know where to start from here. Can anyone point me into the right direction with a guide or example? Help would be greatly appreciated! Thank you

Upvotes: 3

Views: 70

Answers (4)

random
random

Reputation: 7891

const inputArr = [
    {
        "year": "2011",
        "activity": "bowling"
    },
    {
        "year": "2009",
        "activity": "shopping",
    },
    {
        "year": "2011",
        "activity": "cooking"
    },
    {
        "year": "2006",
        "activity": "singing"
    }
];

const outputArr = inputArr.sort((objA, objB) => Number(objA.year) - Number(objB.year))
    .reduce((accu, obj) => {
        const len = accu.length;
        if(len == 0 || accu[len-1].year !== obj.year) {
            accu.push(obj);
        } else {
            accu[len-1].activity += ', ' + obj.activity;
        }
        return accu;
    }, []);

console.log(outputArr);

Upvotes: 0

Saurabh Yadav
Saurabh Yadav

Reputation: 3386

you can simply use for loop

    var mem = {};
    for(var i = 0; i < arr.length; i++) {
        var currentItem = arr[i];
        var year = currentItem['year'];
        var activity =  currentItem['activity'];
        if(!mem.hasOwnProperty(year)) {
            mem[year] = { 'year' : year, "activity": []};
        }
        mem[year]['activity'].push(activity);
    }

    var final = Object.values(mem);

Upvotes: 1

Orelsanpls
Orelsanpls

Reputation: 23515

Instead of checking if the year already exists in your accumulator : Check and modify.

const arr = [{
    year: '2011',
    activity: 'bowling',
  },
  {
    year: '2009',
    activity: 'shopping',
  },
  {
    year: '2011',
    activity: 'cooking',
  },
  {
    year: '2011',
    activity: 'cooking',
  },
  {
    year: '2006',
    activity: 'singing',
  },
];

const new_arr = arr.reduce((tmp, x) => {
  // Already exist
  const exist = tmp.find(y => y.year === x.year);

  if (exist) {
    // Only add not existing activities to avoid duplicates
    if (exist.activity.indexOf(x.activity) === -1) {
      exist.activity = `${exist.activity}, ${x.activity}`;
    }

    return tmp;
  }

  tmp.push(x);

  return tmp;
}, []);

console.log(new_arr);

Upvotes: 0

CertainPerformance
CertainPerformance

Reputation: 370879

Try reduce-ing the activity to an array in the accumulator first, then join each activity property by commas afterwards. You can achieve this with a single reduce, which is O(N), a some inside of it will make it O(N^2), which is not necessary and probably undesirable:

var arr = [
    {
        "year": "2011",
        "activity": "bowling"
    },
    {
        "year": "2009",
        "activity": "shopping",
    },
    {
        "year": "2011",
        "activity": "cooking"
    },
    {
        "year": "2006",
        "activity": "singing"
    }
];
const output = Object.values(
  arr.reduce((a, { year, activity }) => {
    if (!a[year]) a[year] = { year, activity: [] };
    a[year].activity.push(activity);
    return a;
  }, {})
);
output.forEach((item) => {
  item.activity = item.activity.join(', ');
});
console.log(output);

Upvotes: 0

Related Questions