0

Here is my code:

  function createMatchList(data) {
    var matchArray = [];
      for (var i = 0; i < initialData.length; i++) {
        var listData = cleanData(initialData[i][data]);
        if (matchArray.length) {
          for (var a = 0; a < matchArray.length; a++) {
            if (matchArray[a][data] == listData) {
              matchArray[a].Count = matchArray[a].Count + 1;
            } else {
              // THIS CAUSES LOOP
              matchArray.push({ [data]: listData, "Count": 1 });
            }
          }
        } else {
          matchArray.push({ [data]: listData, "Count": 1 });
        }
      }
    }

Essentially, this appears to work outside of when a matching object isn't found, I have an else to push that object to the array and it causes a loop.

I'm not sure why this would happen and I'm totally lost..

I have an initial if/else to see if the array is empty, if it is empty, push the initial object into the array, past this point if the array isn't empty, I check the array using a for loop and the if statement works, but my else statement causes the loop. If I were to take that matchArray.push({ [data]: listData, "Count": 1 }); out of the else statement and just console.log something, it would successfully log for each additional iteration in the first for loop for the initialData.

And just to give an idea of what the array looks like with an object in it:

[
   {
      Date: "27 June 1911", 
      Count: 1
   }
]

My goal is to search the Array for matching Dates and if there is a match, don't push to the Array but instead update the Count. The reason for this is I have a huge raw JSON file with duplicates and I'm trying to create a new data source removing duplicates but counting the occurrences.

Thanks

7
  • 1
    use Array.filter() Commented May 9, 2019 at 18:29
  • show desired input and output Commented May 9, 2019 at 18:31
  • @DennisVash, the input is just a string with the raw date like 27 June 1911. The output would be what is shown above with the Date and Count in the object. the 'data' in the function is 'Date'. Commented May 9, 2019 at 18:37
  • @melpomene sorry, I had typoed. Fixed the code. I had a '(' in the wrong spot in the example above, but not in my actual code. Commented May 9, 2019 at 18:38
  • 1
    Yes, of course. See minimal reproducible example (and ericlippert.com/2014/03/05/how-to-debug-small-programs while you're at it). Commented May 9, 2019 at 18:46

2 Answers 2

2

Use Set and Array.filter():

[...new Set(dates)].map(date => ({
  date,
  count: dates.filter(currDate => date === currDate).length
}));

Note: By convention object keys should be lowercased, date and not Date.

Or if you feel brave:

const counts = {};
dates.forEach(date => (counts[date] = (counts[date] || 0) + 1));

const dates = [
  '27 June 1911',
  '27 June 1952',
  '27 March 1911',
  '27 June 1952',
  '24 June 1911',
  '27 June 1952'
];

const datesCount = [...new Set(dates)].map(date => ({
  date,
  count: dates.filter(currDate => date === currDate).length
}));

console.log('datesCount', datesCount);


const counts = {};
dates.forEach(date => (counts[date] = (counts[date] || 0) + 1));

const dateCount2 = Object.entries(counts).map(([date, count]) => ({
  date,
  count
}));

console.log('dateCount2', dateCount2);


// Make unique array of dates.
const datesSet = [...new Set(dates)];

// Count by filtering the array and getting it's length.
const datesCount = datesSet.map(date => ({
  date,
  count: dates.filter(currDate => date === currDate).length
}));
Sign up to request clarification or add additional context in comments.

3 Comments

Quick question for you if you don't mind. In this const matchCount = [...new Set(matchArray)].map(data => ({ data, count: matchArray.filter(currData => data === currData).length })); What if I want the 'data' object to be named based on a value in another variable? So in my code example, you will see where I'm bring in 'data' in the function. This could be, Data, Place, Time, etc... how could I make that object Dynamic? I assumed it would be [data] but that doesn't appear to work. Thanks again.
{ [myKey]: 'hello' }; should work or myObj[myKey] = 'hello', consider asking a new question, you can send a link to me and I'll help.
No worries, this is what I was doing, so I will just mess with it a bit. Not sure why it isn't working, but thank you!
1

How important is performance and are you using >= 2015? If so, you could just map instead and reduce some code complexity like this answer:

const counts = new Map([...new Set(a)].map(
    x => [x, a.filter(y => y === x).length]
));

Then to get the count you would just call:

counts.get(x)

In the case where you need to store it in an object that looks exactly as you've outlined above, I would do something like:

let unique = Set(dates);
var matchArray = [];

unique.forEach(function (date) {
    matchArray.push({ 
        "Date": date, 
        "Count": dates.filter(x => x === date).length 
    });
});

2 Comments

Hey Ashley, thanks for the reply. I still need to store the counts in the object for reporting purposes to essentially say, on 'x' date, we had 'y' occurrences.
Edited my example, but didn't test. Good luck!

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.