1

I have an array and i would like to find all neighboring matches and count them, then return the count, performed in a loop like .map() so it wont be necessary to store a memory of what was counted beyond the current element. i need to use this number of current elements to reserve enough spaces for each group of elements

array = [ball, batter, batter, amount, amount, github, github, github, account, account, account, account, account, account, account, github, github, github]

example of desired results from this array would be: on first loop would return 1, second loop would return 2, then 2, then 3, then 7, then 3

and this count would be used as a variable to reserve space, something like

number to reserve: count

so through each loop, the variable count would be changed and updated to the current elements count, and the loop that counts would not stop until the next element is not a match for the current element, and the variable count will also not be available for use until all concurrent matches are found, so if i put console.log(count) at the end of the function i would get each number output individually

peter
  • 169
  • 1
  • 1
  • 9
  • What do you mean by _concurrent matches_? I feel like you can just delete the word _concurrent_ from your question. In computing, _concurrent_ typically means something entirely different to the way in which you're trying to use that word. Did you mean _consecutive_? – Wyck Nov 17 '21 at 03:16
  • Can you explain what actually problem you solve – A1exandr Belan Nov 17 '21 at 03:17
  • i have a blank space, and i need to know how many spaces each individual word needs, ball needs one space reserved. batter needs two spaces reserved. amount needs two spaces reserved – peter Nov 17 '21 at 03:20
  • 1
    why not just use a dictionary and count in a single loop. – DecPK Nov 17 '21 at 03:27
  • Check ansewers on this [thread](https://stackoverflow.com/q/5667888/87713) – A1exandr Belan Nov 17 '21 at 03:32
  • thanks @decpk I was having trouble constructing the loop, i couldnt get my head around how to do it. @FFire those solutions count elements wherever they appear in the array, i only want to count neighboring groups, so in my example `github` should show two two groups of three, not one group of six. the numbers should also appear in the order of the groups they represent (not alphabetical) – peter Nov 17 '21 at 03:57

3 Answers3

2

You can easily count the consecutive string in an array as:

const array = ["ball", "batter", "batter", "amount", "amount", "github", "github", "github", "account", "account", "account", "account", "account", "account", "account", "github", "github", "github"]

const result = [];
let last = array[0], lastSameIndex = 0;
for (let i = 1; i < array.length; ++i) {
  if (array[i] !== last) {
    result.push(i - lastSameIndex);
    lastSameIndex = i;
    last = array[i];
  }
}
result.push(array.length - lastSameIndex);

console.log(result);

Let's declare some initial values as

last = array[0], so last = "ball", and lastSameIndex = 0

So we have to start from the index 1 and we only have to consider a single case where the two elements are not equal i.e. array[i] !== last. If they are not equal then we have to push the count of same element till now as:

result.push(i - lastSameIndex);

Now, we have to update the new value and index i.e. last element from where we have to count that element again.

lastSameIndex = i;
last = array[i];

So far so good, but we also have to handle a case where the loop ends, In this case we have to push the count of last element from where the count started i.e. last started or lastSameIndex till the last element.

result.push(array.length - lastSameIndex);

Second solution

const array = [ "ball", "batter", "batter", "amount", "amount", "github", "github", "github", "account", "account", "account", "account", "account", "account", "account", "github", "github", "github"];

let lastStr = "",
  num = 0;
const result = array
  .map((s) => {
    if (lastStr !== s) {
      lastStr = s;
      num = num === 0 ? 1 : 0;
    }
    return num;
  })
  .join("")
  .match(/(\d)\1*/g)
  .map((s) => s.length);
  
console.log(result);
DecPK
  • 24,537
  • 6
  • 26
  • 42
2

So loop each item, if it's not equal to the last item, push 1, else add 1 to the last number in the array.

const items = ["ball", "batter", "batter", "amount", "amount", "github", "github", "github", "account", "account", "account", "account", "account", "account", "account", "github", "github", "github"]

const results = [];

items.forEach((item, i) => {
    if (items[i - 1] !== item) return results.push(1);

    const last = results.length - 1;
    results[last] = results[last] + 1;
});

console.log(results);
Steve
  • 4,372
  • 26
  • 37
1
  • Try to join the array into string seperated with comma by array.join(","): ball,batter,batter,amount,amount,github,github,github
  • Use regex: /([a-z]+,)\1*/gi to match same repeated word Gives: ['ball,', 'batter,batter,', 'amount,amount,', 'github,github,github,...]
  • Count how many word in each string of array by using s.split(',').length-1

Script:

array.join(",").match(/([a-z]+,)\1*/gi).map((s) => `${s.split(',').length-1}`);

Result: ['1', '2', '2', '3', '7', '2']

XMehdi01
  • 5,538
  • 2
  • 10
  • 34
  • 1
    Isn't this is like the solution from this answer [link](https://stackoverflow.com/questions/68124835/javascript-count-the-duplicate-array-values-until-it-changes/68124886#) – DecPK Nov 18 '21 at 14:41
  • AFAIT, But this solution will be not so efficient because regex will have to do much more work as compared to direct string comparison – DecPK Nov 18 '21 at 14:44
  • Yeah, it is the same, but in this we dealing with words not chars, but the same idea! – XMehdi01 Nov 18 '21 at 14:46
  • Unfortunately, it is not efficient as if we did it with for-loop and the words should not contain `,` comma! – XMehdi01 Nov 18 '21 at 14:49
  • 1
    Yeah, I agree but this can be an alternate solution. Great – DecPK Nov 18 '21 at 14:49
  • Yeah, An alternate but not perfect as your answer! – XMehdi01 Nov 18 '21 at 14:51