Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I used your jsperf as a reference, for some of the finer points of script. I really, really liked your 'hash' code, so I totally stole it. Mine uses a different method to generate the string used to make the hash, which seems to be a little faster, which increases the performance, according to the 'browserscope' charts. I include in my test a 'too much recursion' proof of concept to show that it has recursion protection, like JSON.stringify and .toSource(). </p> <p><a href="http://jsfiddle.net/dTC4g/" rel="noreferrer">My jsfiddle</a> shows that the code returns the format you need. <a href="http://jsperf.com/group-by-complex-fast" rel="noreferrer">My jsperf</a> seems to indicate that it outperforms the posted solution. I also included the linq.js solution, but it performs pretty bad in FireFox for me. It works comparably in Safari, Chrome, an IE, but not faster than mine, except in IE. I even tried it on my phone, and still I have the same performance difference. I have personally tested it in the latest versions of all browsers in a side-by-side to the posted solution, and mine out performs by around 40% across each of them. What are everyone's thoughts?</p> <p>Here is my code:</p> <pre><code>var arr = [ { N: 10, Name: "Foo" }, { N: 10, Name: "Bar" }, { N: 20, Name: "Foo" }, { N: 20, Name: "Bar" } ]; var poc = { name:'blah', obj:{} }; poc.obj = poc; var arrComplex = [ { N: { Value: 10, TooMuchRecursionProofPOC:poc }, Name: "Foo" }, { N: { Value: 10, TooMuchRecursionProofPOC:poc }, Name: "Bar" }, { N: { Value: 20, TooMuchRecursionProofPOC:poc }, Name: "Foo" }, { N: { Value: 20, TooMuchRecursionProofPOC:poc }, Name: "Bar" } ]; var eArr = Enumerable.From(arr); var eArrComplex = Enumerable.From(arrComplex); function setup_hashers() { // recursion protection idea var rp = '_rp'+(Math.random()*10000000); function tstr() { var out = '', i = ''; if (this[rp]) { this[rp] = undefined; return out; } for (i in this) if (i != rp &amp;&amp; this.hasOwnProperty(i)) out += this[i] instanceof Object ? ((this[rp] = true) &amp;&amp; this[i] != this &amp;&amp; !this[i][rp] ? tstr.call(this[i]) : '') : (this[i].toString || tstr).call(this[i]); return out; }; Number.prototype.GetHashCode = function() { return this.valueOf(); }; Object.prototype.GetHashCode = function() { var s = (this instanceof Object ? tstr : this.toString || tstr).call(this), h = 0; if (s.length) for (var i = 0; i &lt; s.length; i++) h = ((h &lt;&lt; 5) - h) + s.charCodeAt(i); return h; }; } function group_by(a, keyFunc, valFunc, comp, as_array) { if (!a.length) return as_array ? [] : {}; var keyFunc = keyFunc || function (e) { return e; }, valFunc = valFunc || function (e) { return e; }; var comp = comp || { Equals: function (a, b) { return a == b; }, Hash: function (e) { return e.GetHashCode(); } }; var hashs = {}, key = '', hash = ''; for (var i = 0; i &lt; a.length; i++) { key = keyFunc(a[i]); hash = comp.Hash(key); if (typeof hashs[hash] != 'undefined') hash = comp.Equals(key, hashs[hash].Key) ? hash : hash + '-' + i; hashs[hash] = hashs[hash] || { Key: key, Elements: [] }; hashs[hash].Elements.push(valFunc(a[i])); } if (as_array) { var out = [], j = '', keys = Object.keys(hashs); for (var j = 0; j &lt; keys.length; j++) out.push(hashs[keys[j]]); return out; } return hashs; }; function group_by_control(a, keyFunc, valFunc) { if (!a.length) return as_array ? [] : {}; var keyFunc = keyFunc || function (e) { return e; }, valFunc = valFunc || function (e) { return e; }; var hashs = {}, key = '', hash = ''; for (var i = 0; i &lt; a.length; i++) { key = keyFunc(a[i]); hashs[key] = hashs[key] || { Key: key, Elements: [] }; hashs[key].Elements.push(valFunc(a[i])); } var out = [], j = '', keys = Object.keys(hashs); for (var j = 0; j &lt; keys.length; j++) out.push(hashs[keys[j]]); return out; }; setup_hashers(); console.log(group_by_control( arr, function(e) { return e.N }, function(e) { return e.Name } )); console.log(group_by( arrComplex, function(e) { return e.N; }, function(e) { return e.Name; }, { Equals: function(a, b) { return a.Value == b.Value }, Hash: function(e) { return e.GetHashCode(); } } )); console.log(group_by( arrComplex, function(e) { return e.N; }, function(e) { return e.Name; }, { Equals: function(a, b) { return a.Value == b.Value }, Hash: function(e) { return e.GetHashCode(); } }, true )); </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
    3. VO
      singulars
      1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload