1

I want to create an array with a uniqueDate value in my array. So if I have this array:

const arr = [
      {
        name: "Edward",
        date: "24 March"
      },
      {
        name: "Banana",
        date: "12 March"
      },
      {
        name: "Edward",
        date: "23 March"
      },
      {
        name: "Edward",
        date: "23 March"
      }
    ]

... then the output will be something like:

[
    {name:"Edward", uniqueDate: 2, totalSubmit: 3},   
    {nama: "Banana",uniqueDate: 1, totalSubmit: 1}
]

The first unique date is 2 because we have 2 different dates: 24 March and 23 March. I've tried to use reduce, but it has some issues.

6
  • Please show us what you have tried so far. Commented Mar 27, 2021 at 20:18
  • Example I have this array: const arr = [ { nama: "Edward", date: "24 March" }, { nama: "Banana", date: "12 March" }, { nama: "Edward", date: "23 March" }, { nama: "Edward", date: "23 March" }, { nama: "Bob", date: "1 March" }, { nama: "Pam", date: "1 March" }, { nama: "Anna", date: "19 March" }, { nama: "Jake", date: "12 March" } ] Commented Mar 27, 2021 at 20:24
  • I reduced it twice, const reducedSales = arr.reduce((acc, item) => { var previousItem = acc.find(findItem => (findItem['nama'] === item['nama']) && (findItem['date'] === item['date'])); // if previous item is false, meaning different Nama Distributor if (!previousItem) { acc.push({ ...item, totalSubmit: 1 }) } else { previousItem.totalSubmit++ } return acc; }, []) Commented Mar 27, 2021 at 20:25
  • and another reduce, const update = reducedSales.reduce((acc, item) => { var previousItem = acc.find(findItem => findItem['nama'] === item['nama']); // if previous item is false, meaning different Nama Distributor if (!previousItem) { acc.push({ ...item, hariKerja: 1 }) } else { previousItem.hariKerja++ } return acc; }, []) console.log(update) Commented Mar 27, 2021 at 20:25
  • @AndrewL64 this is the output: [ { nama: 'Edward', date: '24 March', totalSubmit: 1, hariKerja: 2 }, { nama: 'Banana', date: '12 March', totalSubmit: 1, hariKerja: 1 }, { nama: 'Bob', date: '1 March', totalSubmit: 1, hariKerja: 1 }, { nama: 'Pam', date: '1 March', totalSubmit: 1, hariKerja: 1 }, { nama: 'Anna', date: '19 March', totalSubmit: 1, hariKerja: 1 }, { nama: 'Jake', date: '12 March', totalSubmit: 1, hariKerja: 1 } ] Commented Mar 27, 2021 at 20:25

2 Answers 2

3

You can use a Map to collect the dates that go with a name (check your spelling in the example data!), and then you can iterate those map entries to both get the dates-array length, and unique count (via Set):

const arr = [{name: "Edward",date: "24 March"},{name: "Banana",date: "12 March"},{name: "Edward",date: "23 March"},{name: "Edward",date: "23 March"}];

let map = new Map(arr.map(o => [o.name, []]));
for (let {name, date} of arr) map.get(name).push(date);
let result = Array.from(map.entries(), ([name, dates]) => 
    ({name, uniqueDate: new Set(dates).size, totalSubmit: dates.length})
);
console.log(result);

If the property name to group by has special characters, like a space, then:

const arr = [{"Full Name": "Edward",date: "24 March"},{"Full Name": "Banana",date: "12 March"},{"Full Name": "Edward",date: "23 March"},{"Full Name": "Edward",date: "23 March"}];

let map = new Map(arr.map(o => [o["Full Name"], []]));
for (let o of arr) map.get(o["Full Name"]).push(o.date);
let result = Array.from(map.entries(), ([name, dates]) => 
    ({"Full Name": name, uniqueDate: new Set(dates).size, totalSubmit: dates.length})
);
console.log(result);

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

4 Comments

Hi, thank you very much for your help. If I may add 1 more question, what if my object name has a space? For example, instead of name, the object name is Full Name. Instead of date, the object name is 'Created At'.
for (let {name, date} of arr) map.get(name).push(date); TypeError: Cannot read property 'push' of undefined So for context, my object name is something like "Full Name", and "Created At".
So the actual array is something like: const arr = [{"Full Name": "Edward","Created At": "24 March"}]; etc
See addition to answer.
1

You can call reduce function to create a key-value pair of each name then, where it contains the name, a Set of unique dates, and totalSubmit. Finally, you can get the values of that object and map it with the unique dates' size.

const arr = [{ name: "Edward", date: "24 March" }, { name: "Banana", date: "12 March" }, { name: "Edward", date: "23 March" }, { name: "Edward", date: "23 March" }];
    
const temp = arr.reduce((acc, { name, date }) => {
   acc[name] = acc[name] || { name, dates: new Set(), totalSubmit: 0 };
   acc[name].totalSubmit++;
   acc[name].dates.add(date);
   return acc;
}, {});
    
const result = Object.values(temp).map(({ name, dates, totalSubmit}) => ({ name, uniqueDate: dates.size, totalSubmit }));
     
console.log(result);

2 Comments

Thank you so much for your answer! May I add 1 more question? What if my object name has space? Example: instead of "name", its "Full Name"
@EdwardTanoto I assume this "Full Name" would be unique. in this case, we can use key = name.split(' ').join('_') which makes Edward Tanoto into Edward_Tanoto

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.