Path: csiph.com!v102.xanadu-bbs.net!xanadu-bbs.net!feeder.erje.net!eu.feeder.erje.net!newsfeed.fsmpi.rwth-aachen.de!newsfeed.straub-nv.de!weretis.net!feeder1.news.weretis.net!news.solani.org!.POSTED!not-for-mail From: Thomas 'PointedEars' Lahn Newsgroups: comp.lang.javascript Subject: Re: function to get frequencies of a char array Date: Fri, 23 Jan 2015 16:52:29 +0100 Organization: PointedEars Software (PES) Lines: 92 Message-ID: <26839541.MRbOrngyXZ@PointedEars.de> References: Reply-To: Thomas 'PointedEars' Lahn Mime-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8Bit X-Trace: solani.org 1422028390 28998 eJwFwYEBwCAIA7CXLAU6zlEm/59gEkxkyzPSY2L+gjWjpGkfYteF41xwyZcV0VeWuz8YdfIBC5MQOg== (23 Jan 2015 15:53:10 GMT) X-Complaints-To: abuse@news.solani.org NNTP-Posting-Date: Fri, 23 Jan 2015 15:53:10 +0000 (UTC) User-Agent: KNode/4.14.2 X-User-ID: eJwFwYEBwDAEBMCVvCIxjuD3H6F3/gWij4WHOZ2PmpfVMSWK59/KGsKww2GJPZwTqoUEadsBNxnelOy8/QNnxBW+ Cancel-Lock: sha1:4ggdL0zKbvBMv3HwfPZz/gu6SFc= X-NNTP-Posting-Host: eJwNwYEBwCAIA7CXBi1VzwEH/5+wJQGZ7qJCjInJNPZbq73I4q4krR3eUMKeg/2zyxlAdT4hwRDJ Xref: csiph.com comp.lang.javascript:26670 Christoph M. Becker wrote: > Evertjan. wrote: >> Try this, using an object as target: >> >> ============================= >> var arr = 'abjcdjjj'.split(''); // source array >> var res = {}; // result object >> >> function frequencies() { >> for(i=0; i< arr.length; i++) { >> if (!res[arr[i]]) >> res[arr[i]] = 0; >> res[arr[i]] +=1; >> }; >> }; >> frequencies(); >> >> console.log(res); // Object {a: 1, b: 1, j: 4, c: 1, d: 1} >> ============================= > > Or maybe using Array.prototype.reduce: > > var a = ['a', 'b', 'j','c', 'd', 'j', 'j', 'j']; > a.reduce(function (prev, curr) { > if (prev.hasOwnProperty(curr)) { > prev[curr]++; > } else { > prev[curr] = 1; > } > return prev; > }, {}); While this works – but I would use “Object.create(null)” instead of “{}” to avoid name collisions –, I find a “for” or “for–in” statement more obvious and compatible: var counts = {}; for (var i = 0, len = a.length; i < len; ++i) { /* NOTE: hasOwnProperty() may be required */ var e = a[i]; e ? ++counts[e] : (counts[e] = 1); } for (var i in a) { /* NOTE: hasOwnProperty() may be required */ var e = a[i]; e ? ++counts[e] : (counts[e] = 1); } “for–in” is more efficient than “for“ and Array.prototype.forEach() with sparse arrays. Array.prototype.forEach() can be used instead if it is supported and the array is insufficiently sparse: a.forEach(function (e, i, a) { var counts = a.counts_ || (a.counts_ = Object.create(null)); (counts[e]) ? ++counts[e] : (counts[e] = 1); }); a.counts_ The advantage of using the Array instance as container is that the scope chain is shorter, which is faster. However, that method, too, can be passed a “this” value: var counts = Object.create(null); a.forEach( function (e) { (this[e]) ? ++this[e] : (this[e] = 1); }, counts); counts Array.prototype.reduce(), if I use it (it needs to be emulated in case it is not available), I reserve for getting a single *primitive* value from an Array instead. For example: var sum = a.reduce(function (prev, curr) { return prev + (+curr); }, 0); (Implicit type conversion is unnecessary if all elements are of type Number.) -- PointedEars FAQ: | SVN: Twitter: @PointedEars2 | ES Matrix: Please do not cc me. / Bitte keine Kopien per E-Mail.