-5

I have string like the following:

11222233344444445666

What I would like to do is output the number followed the times it was displayed: 112433475163

Question is, I want this to be efficient. I can store this in an object as the following:

1: { id: 1, displayed: 2},
2: { id: 2, displayed: 1},
3: { id: 3, displayed: 2}, 

etc.

I can access this object and increment displayed.

My issues is, there is no guarantee in the order. I would like to store the keys in the order they are in the string. How do I accomplish the importance of the order in the object?

KingKongFrog
  • 12,668
  • 17
  • 63
  • 111
  • why would you access that object and increment 'displayed' property? Do you want to be able to transform that object back into a string ? – RomanPerekhrest Mar 10 '16 at 21:34
  • why does order matter? object lookup is very fast in javscript.. its an associative array. relative: http://stackoverflow.com/questions/5888652/javascript-array-lookup-efficiency-associative-vs-stored-associative – Collin Mar 10 '16 at 21:36
  • 1
    Objects happen to iterate by definition order in all browsers, but it's not guaranteed by the spec: http://stackoverflow.com/questions/280713/elements-order-in-a-for-in-loop – itsananderson Mar 10 '16 at 22:27

4 Answers4

0

This is a proposal for run length coding with an array which holds infomation about one charcter and the count of it:

{
    "char": "1",
    "count": 2
},

var string = "11222233344444445666",
    array = function () {
        var r = [], o = {};
        string.split('').forEach(function (a, i, aa) {
            if (a !== aa[i - 1]) {
                o[a] = { char: a, count: 0 };
                r.push(o[a]);
            }
            o[a].count++;
        });
        return r;
    }(string);

document.write('<pre>' + JSON.stringify(array, 0, 4) + '</pre>');
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
  • This solution won't work with strings that contain non-contiguous groupings of the same number, e.g. "1211" – itsananderson Mar 10 '16 at 22:23
  • @itsananderson, is that the question? the question was how to retain the order with the wanted information, like character and count. or do i miss something? – Nina Scholz Mar 11 '16 at 07:40
  • 1
    I suppose it's not technically listed as a requirement, but the author's initial solution did seem to be implementing a more general-purpose character occurrence counter, which seemed to imply that the string could be a random collection of numbers. You might be right though. – itsananderson Mar 11 '16 at 15:52
0

Quick solution with for loop:

var str = "7771122229933344444445666",
    obj = {},
    len = str.length,
    val = null, 
    count_str = "",
    key = "";

for (var i = 0; i < len; i++) {
    val = str[i], key = 'k' + val;
    if (!obj[key]) {
       obj[key] = {'id': val, 'displayed': 1}; 
    } else {
        obj[key].displayed++;
    }
}
for (var p in obj) {
    count_str += obj[p]['id'] + obj[p]['displayed'];
}

console.log(count_str); // "7312249233475163"
RomanPerekhrest
  • 73,078
  • 4
  • 37
  • 76
-1

You could store an additional array with the order of the numbers, which you only append to if the object doesn't yet contain the given number. Then once you're done counting, iterate through that array and output the number and the count from the lookup dictionary.

var chars = "1234576123452345".split("");
var order = [];
var hash = {};
chars.forEach(function(char) {
  if (!hash[char]) {
    hash[char] = 1;
    order.push(char);
  } else {
    hash[char]++;
  }
});

console.log(order.map(function(char) {
  return char + hash[char];
}).join(""));

// "12233343537161"
itsananderson
  • 763
  • 5
  • 9
  • I don't know why this was so quickly downvoted. Though I can see one issue is that if the first value received is not in order for the series of hashes you make, you will get values back out of sorted order. e.g. try with var chars = "1234765123452345"; also all strings are arrays of characters. no need to split like that – Corvus Crypto Mar 10 '16 at 21:45
  • The request was to output the characters in the order they appear in the string, not sorted, so I think my solution is correct. Also, strings don't have a forEach method, so splitting it is necessary if you want to avoid using a for loop. – itsananderson Mar 10 '16 at 21:53
  • I was hinting at you should use a for loop because of performance (http://jsperf.com/for-vs-foreach/66) :P either way. I must have misinterpreted the question. – Corvus Crypto Mar 10 '16 at 21:55
  • If you're optimizing for the absolute fastest solution, a for loop is the right choice, but for reasonably small strings it's worth using forEach for the improvement in code clarity. – itsananderson Mar 10 '16 at 22:03
  • Good points. I'm not really used to the JavaScript-esque styles of coding I guess. But yeah speed performance is something I'm used to being required to think of. I'll try to keep this in mind as I develop in JS for the future that this is preferred over for loops – Corvus Crypto Mar 10 '16 at 22:04
-1

because you have such a small set of distinct numbers, I seen no reason why you can't use a array (yeah it's not super ideal memorywise if you skip values and it becomes sparse, but for such a small subset it won't affect you enough to worry of it). Then you can use (number-1) as the index and increment that number as needed.

var counts = [];
var str = "11222233344444445666";
for(var i in str){
    var index = parseInt(str[i])-1
    counts[index] = (counts[index]||0)+1;
}
for(var i in counts){
        var which = 1+parseInt(i);
    var count = counts[i];
    console.log("# of " + which +"'s: "+count);
}

https://jsfiddle.net/ga0fqpqn/

note: You shouldn't need the parseInt(i)... just +i should work but I think jsfiddle has a bug with it about it defaulting i to handle like a string.

Corvus Crypto
  • 1,782
  • 1
  • 9
  • 14
  • 1
    The reason 1+i doesn't work is because it's treated as concat instead of add, so the result is, for example, "11". – itsananderson Mar 10 '16 at 21:58
  • yeah I know that's what's happening but when I receive an integer I'm just used to not having to assert it as an int. Probably just never noticed before – Corvus Crypto Mar 10 '16 at 22:00