0

My goal is to turn

['sara', 'mike', 'sara','sara','Jon'] 

into

'sara', 'mike', 'sara(1)','sara(2)' 'Jon'

Ive seen some solutions when counting the total number of duplicates, however, couldnt find anything for what I am trying to do..

ps. I cannot use sort() as the names should stay where they were in the original array..

I tried using a regular for loop but nothing really worked, I also think a map approach would probably be good, but cant figure out how to do that.

Thank you!

EDIT:

I actually came up with this here:

function words(arr){
  var result=[];
  var count=0;
 for (var i=0; i<arr.length; i++){
    if (result.indexOf(arr[i])==-1){
    result.push(arr[i]);    
    }
    else {
        count++;
        result.push(arr[i]+"("+count+")");
    }

 }
 return result.join(',');
}

words(['sara', 'mike', 'sara','sara','Jon'] );

and it works except it returns 'sara,mike,sara(1),sara(2),Jon' instead of 'sara','mike,'sara(1)','sara(2)','Jon'

Anyone knows how to change that? I tried join, split etc already..

javascripting
  • 1,135
  • 4
  • 25
  • 46
  • If you found solutions for counting duplicates, then can't you just modify the string whenever the count is greater than 1? –  Jun 01 '16 at 22:27
  • no,it doesn't work or I don't know how to make it work. – javascripting Jun 01 '16 at 22:34
  • Then show what you've tried so that we can help you understand where you made a mistake. –  Jun 01 '16 at 22:35
  • @javascripting Try something like this https://jsfiddle.net/Lg0wyt9u/934/ – Nenad Vracar Jun 01 '16 at 22:38
  • Note that your solution works only if just one name is repeating, but if more than one name is repeating your solution will fail (i.e. `['sara','mike', 'sara', 'mike']`) – Ahmad Ibrahim Jun 03 '16 at 14:55

6 Answers6

1
var nameArr = ['sara', 'mike', 'sara','sara','Jon'];
var nameTrack = {};
var resultArr = nameArr.map(function(name) {
  if(typeof nameTrack[name] === 'undefined') {
    nameTrack[name] = 0;
    return name;
  }
  return name + '(' + ++nameTrack[name] + ')';
});

Some points of explanation:

You can't just use nameTrack[name] cast to a boolean on the 4th line because 0 is non-truthy.

The ++ preceeds nameTrack[name] so that the incrementation happens first. If you put it afterwards, the number would only increment after the string was formed.

Map is an array function that takes each value of the array, modifies it, and returns it to the array. See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

Russbear
  • 1,261
  • 1
  • 11
  • 22
  • 1
    You forgot to assign the new array returned by the `map` function to some variable (i.e. `var result = nameArr.map(...);`) – Ahmad Ibrahim Jun 03 '16 at 15:22
1

Try this:

function countWords (words) {
    var wordsCounter = {}, results = [];
    words.forEach(function (word) {
        if (!wordsCounter.hasOwnProperty(word)) {
            results.push(word);
            wordsCounter[word] = 1;
        }
        else {
            results.push(word + '(' + (wordsCounter[word]++) + ')');
        }
    });
    return results;
}    
Lior Erez
  • 1,852
  • 2
  • 19
  • 24
0

here is a regular loop solution. tested and got your expected results

var myArray = ['sara', 'mike', 'sara','sara','Jon'] 

                var arrayResult = [];

                for (var i=0;i<myArray.length;i++)
                {
                    arrayResult.push(countPlease(i));

                }
                console.dir(arrayResult);
                //'sara', 'mike', 'sara(1)','sara(2)' 'Jon'

            function countPlease(index)//index of where you're current at
            {
                //loop backword
                var txt = myArray[index]; // don't count
                var c = 0;
                for (var i=index-1;i>-1;i--) //don't count itself
                {
                    if(myArray[i]==txt)
                    {
                        c++
                    }
                }
                if(c>0)
                {
                    return txt+ ' (' + c+')'
                }
                else
                return txt;

            }
chungtinhlakho
  • 870
  • 10
  • 21
0

Here is a JSFiddle and here is a solution:

var a = ['sara', 'mike', 'sara','sara','Jon'];

for(var i=0; i<a.length; i++){
    var repeated = 1;
    for(var j=i; j<a.length; j++){
        if(i == j){
        continue;
    }
    if(a[i].toLowerCase() == a[j].toLowerCase()){
        a[j] = a[i]+repeated;
        repeated++;
    }
  }
}
Orbiting Eden
  • 1,522
  • 13
  • 16
  • Could you explain the 2 loops-and i=0 and j=i ? As I understand, the first word (f.e. sara is being compared to every other word in the array because of the second loop, then the second word is being compared to every other word etc-: i starts with 'sara' and j starts with wherever i starts? – javascripting Jun 01 '16 at 22:49
  • Why not just `for (var j = i+1;..` instead of `if (i == j) continue;` ? .. Also, this solution is O(n^2) complexity, means if `a = ['mike', 'sara'... ...];`, you'll compare `mike` with each of these `sara`'s unnecessarily. – Ahmad Ibrahim Jun 03 '16 at 15:13
0

With the help of an object, which counts the words:

if(key in obj) { // Found the same word
    ...
    obj[key] += 1; 
} else { // Only one time found
    ...
    obj[key] = 0;
}

In total:

var names = ['sara', 'mike', 'sara', 'sara', 'Jon'];

function countWords(arr) {
    var res = [];
    var obj = {};

    names.forEach(function(name) {
        if(name in obj) {
            obj[name] += 1;
            res.push(name + "(" + obj[name] + ")");
        } else {
            obj[name] = 0;
            res.push(name);
        }
    });

    return res.join(",");
}

var res = countWords(names);
console.log(res);
-2

var arr = ['sara', 'mike', 'sara','sara','Jon'];
var number_detail = {};
$.each(arr, function(key, val){
  if (typeof number_detail[val] != 'undefined'){
    var cur_count = number_detail[val];
    number_detail[val] = cur_count+1;
    arr[key] = val+'('+number_detail[val]+')';
  }
  else {
    number_detail[val] = 0;
  }
});
CY_
  • 7,170
  • 1
  • 15
  • 26