Notice: Undefined offset: 1 in /home/plusensd/steelhammer.com.ua/route.php on line 89
function ClassName(x) { return x ? (x.constructor ? x.constructor.toString().substring('function '.length, x.constructor.toString().indexOf('(')).trim() : undefined) : undefined; } function XFunc(func) { if (typeof func == 'object') { var funcBody = 'return true'; for (var v in func) { if (typeof(func[v]) == 'string') funcBody += ' && x.' + v + '=="' + String(func[v]).replace(/"/g, '\"') + '"'; else funcBody += ' && x.' + v + '==' + String(func[v]); } return Function('x', funcBody + ';'); } else if (typeof func == 'string') return Function('x', 'y', 'z', 't', 'return ' + func + ';'); else return func; } Array.prototype.ForEach = function (f) { f = XFunc(f); for (var i = 0; i < this.length; i++) { var ret = f.call(this[i], this[i], i); if (ret !== undefined) return ret; } } Array.prototype.Add = function (item) { this.push(item); return this; } Array.prototype.AddOnce = function (item) { if (!this.Contains(item)) { this.Add(item); } return this; } Array.prototype.Aggregate = function (seed, accumulator) { // accumulator is func(total, next, index). Example of using (facterial function): Aggregate(1, 'x * y') accumulator = XFunc(accumulator); var total = seed; this.ForEach(function (x, i) { total = accumulator(total, x, i); }); return total; } Array.prototype.All = function (f) { f = XFunc(f); return !this.ForEach(function (x, i) { if (!f.call(x, x, i)) return true; }); } Array.prototype.Any = function (f) { if (f) { f = XFunc(f); return Boolean(this.ForEach(function (x, i) { if (f.call(x, x, i)) return true; })); } else return Boolean(this.Count()); } Array.prototype.Empty = function (f) { return !this.Any(f); } Array.prototype.Average = function (f) { if (f) return this.Where(f).Average(); return this.Count() ? this.Sum() / this.Count() : undefined; } Array.prototype.CloneWithoutItems = function () { var result = []; for (var i in this) if (!/^\d+$/.test(i)) result[i] = this[i]; return result; } Array.prototype.Clone = function () { return this.Range(); } Array.prototype.Concat = function (a) { var result = this.Clone(); result.push.apply(result, a); for (var i in a) if (!/^\d+$/.test(i)) result[i] = a[i]; return result; } Array.prototype.Contains = function (x) { return Boolean(this.ForEach(function(a) { if (a === x) return true; })); } Array.prototype.Count = function (f) { return f ? this.Where(f).Count() : this.length; } Array.prototype.Cycle = function (shift) { shift %= this.Count(); return this.Skip(-shift).Concat(this.Take(-shift)); } Array.prototype.Distinct = function () { result = this.CloneWithoutItems(); this.ForEach(function (x) { if (!result.Contains(x)) result.push(x); }); return result; } Array.prototype.ElementAt = function (i) { return i >= 0 && i < this.Count() ? this[i] : undefined; } Array.prototype.Exclude = function (f) { var result = this.CloneWithoutItems(); f = XFunc(f); this.ForEach(function (x, i) { if (!f.call(x, x, i)) result.push(x); }); return result; } Array.prototype.Except = function (a) { if (ClassName(a) != 'Array') a = [a]; return this.Where(function (x) { return !a.Contains(x) }); } Array.prototype.IndexOf = function(x) { return this.FirstIndex(function(a) { return a === x; }); } Array.prototype.First = function (f) { if (f) { f = XFunc(f); return this.ForEach(function (x, i) { if (f.call(x, x, i)) return x; }); } else return this.ElementAt(0); } Array.prototype.FirstIndex = function (f) { if (f) { f = XFunc(f); return this.ForEach(function (x, i) { if (f.call(x, x, i)) return i; }); } else if (this.Count()) return 0; } Array.prototype.LastIndex = function (f) { if (f) { f = XFunc(f); return this.Reverse().ForEach(function (x, i) { if (f.call(x, x, i)) return i; }); } else if (this.Count()) return 0; } Array.prototype.FullJoin = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.SelectMany(function (x) { var ok = outerKey(x); if (ok !== undefined) return a.Select(function (y) { ik = innerKey(y); if (ok === ik) return f.call(x, x, y); if (ik === undefined) return f(undefined, y); }); else return [f.call(x, x, undefined)]; }); } Array.prototype.GroupBy = function (f) { f = XFunc(f); var groups = []; var that = this; this.ForEach(function (x, i) { var key = f(x, i); var keyIndex = groups.FirstIndex(function (x) { return x.key === key }); if (keyIndex === undefined) { var newItem = that.CloneWithoutItems(); newItem.key = key; groups.push(newItem); keyIndex = groups.length - 1; } groups[keyIndex].push(x); }); return groups; } Array.prototype.GroupJoin = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.Select(function (x) { var ok = outerKey(x); if (ok !== undefined) { var y = a.Where(function (y) { return ok === innerKey(y); }); if (y.Count()) return f.call(x, x, y); } }); } Array.prototype.Intersect = function (a) { return this.Where(function (x) { return a.Contains(x) }); } Array.prototype.Join = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.SelectMany(function (x) { var ok = outerKey(x); if (ok !== undefined) return a.Select(function (y) { if (ok === innerKey(y)) return f.call(x, x, y); }); }); } Array.prototype.Last = function (f) { return f ? this.Reverse().First(f) : this.ElementAt(this.Count() - 1); } Array.prototype.LeftGroupJoin = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.Select(function (x) { var ok = outerKey(x); if (ok !== undefined) { var y = a.Where(function (y) { return ok === innerKey(y); }); if (y.Count()) return f.call(x, x, y); else return f.call(x, x, undefined); } }); } Array.prototype.LeftJoin = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.SelectMany(function (x) { var ok = outerKey(x); if (ok !== undefined) return a.Select(function (y) { if (ok === innerKey(y)) return f.call(x, x, y); }); else return [f.call(x, x, undefined)]; }); } Array.prototype.Max = function (f) { if (f) return this.Where(f).Max(); return this.Aggregate(this.First(), 'Math.max(x, y)'); } Array.prototype.MaxIndex = function (f) { var max = f ? this.Max(f) : this.Max(); return this.FirstIndex(function (x) { return x === max; }); } Array.prototype.Min = function (f) { if (f) return this.Where(f).Min(); return this.Aggregate(this.First(), 'Math.min(x, y)'); } Array.prototype.MinIndex = function (f) { var min = f ? this.Min(f) : this.Min(); return this.FirstIndex(function (x) { return x === min; }); } Array.prototype.DoOrderBy = function (f) { f = XFunc(f); return this.sort(function (x, y) { var fx = f.call(x, x); var fy = f.call(y, y); return fx < fy ? -1 : (fx > fy ? 1 : 0); }); } Array.prototype.OrderBy = function (f) { return this.Clone().DoOrderBy(f); } Array.prototype.DoOrderByDesc = function (f) { f = XFunc(f); return this.sort(function (x, y) { var fx = f.call(x, x); var fy = f.call(y, y); return fx < fy ? 1 : (fx > fy ? -1 : 0); }); } Array.prototype.OrderByDesc = function (f) { return this.Clone().DoOrderByDesc(f); } Array.prototype.DoOrderByDescending = Array.prototype.DoOrderByDesc; Array.prototype.OrderByDescending = Array.prototype.OrderByDesc; Array.prototype.Range = function (from, to) { var result = to || to === 0 ? this.slice(from, to) : this.slice(from); for (var i in this) if (!/^\d+$/.test(i)) result[i] = this[i]; return result; } Array.prototype.DoRemove = function (from, count) { if (count !== 0) { if (arguments.length) { count = count || 1; for (i = from + count; i < this.length; i++) this[i - count] = this[i]; this.length = this.length - count; } else this.length = 0; } return this; } Array.prototype.Remove = function (from, count) { if (count === 0 || !arguments.length) return this.CloneWithoutItems(); return this.Take(from).Concat(this.Skip(from + (count || 1))); } Array.prototype.DoRemoveFirst = function (f) { return this.DoRemove(this.FirstIndex(f)); } Array.prototype.DoRemoveItem = function (item) { while (this.Contains(item)) { this.DoRemoveFirst(function (x) { return x === item; }); } return this; } Array.prototype.DoRemoveItems = function (items) { var that = this; items.ForEach(function () { that.DoRemoveItem(this); }); return this; } Array.prototype.RemoveFirst = function (f) { return this.Remove(this.FirstIndex(f)); } Array.prototype.DoRemoveLast = function (f) { return this.DoRemove(this.LastIndex(f)); } Array.prototype.RemoveLast = function (f) { return this.Remove(this.LastIndex(f)); } Array.prototype.DoRemoveWhere = function (f) { while (this.Any(f)) { return this.DoRemoveFirst(f); } } Array.prototype.DoReverse = function (f) { return this.reverse(); } Array.prototype.Reverse = function (f) { return this.Clone().DoReverse(); } Array.prototype.RightJoin = function (a, outerKey, innerKey, f) { outerKey = XFunc(outerKey); innerKey = XFunc(innerKey); f = XFunc(f); return this.SelectMany(function (x) { var ok = outerKey(x); if (ok !== undefined) return a.Select(function (y) { ik = innerKey(y); if (ok === ik) return f.call(x, x, y); if (ik === undefined) return f(undefined, y); }); }); } Array.prototype.Select = function (f) { f = XFunc(f); var result = []; this.ForEach(function (x, i) { var y = f.call(x, x, i); if (y !== undefined) result.push(y); }); return result; } Array.prototype.SelectAll = function (f) { f = XFunc(f); var result = []; this.ForEach(function (x, i) { result.push(f.call(x, x, i)); }); return result; } Array.prototype.SelectMany = function (f) { f = XFunc(f); var result = []; this.ForEach(function (x, i) { result.push.apply(result, f.call(x, x, i)); }); return result; } Array.prototype.Single = function (x) { var s = this.Where(function (a) { return a === x; }); return s.Count() == 1 ? x : undefined; } Array.prototype.SingleIndex = function (x) { var X = function (a) { return a === x; }; var s = this.Where(X); return s.Count() == 1 ? this.FirstIndex(X) : undefined; } Array.prototype.Skip = function (countOrFunc) { if (typeof countOrFunc == 'string' || typeof countOrFunc == 'function') { var f = XFunc(countOrFunc); var i = this.FirstIndex(function (x) { return !f.call(x, x); }); return this.Range(i); } return this.Range(countOrFunc); } Array.prototype.SkipLast = function (count) { return this.Range(0, -count); } Array.prototype.Sum = function (f) { if (f) return this.Where(f).Sum(); return this.Aggregate(0, 'x + y'); } Array.prototype.Take = function (countOrFunc) { if (typeof countOrFunc == 'string' || typeof countOrFunc == 'function') { var f = XFunc(countOrFunc); var i = this.FirstIndex(function (x) { return !f.call(x, x); }); return this.Range(0, i); } return this.Range(0, countOrFunc); } Array.prototype.TakeLast = function (count) { return this.Range(count); } Array.prototype.Union = function (a) { return this.Concat(a.Except(this)); } Array.prototype.Where = function (f) { var result = this.CloneWithoutItems(); f = XFunc(f); this.ForEach(function (x, i) { if (f.call(x, x, i)) result.push(x); }); return result; } Array.prototype.Zip = function (a, f) { // f is func(first, second) where first is item of this, and second is item of a f = XFunc(f); var t = a.Count() < this.Count() ? this.Take(a.Count()) : this; return t.Select(function (x, i) { return f.call(x, x, a.ElementAt(i)); }); } range = function (from, to, step) { if (arguments.length < 2) { to = from; from = 0; } from = from || 0; to = to || 0; step = step || 1; var result = []; if (step > 0) for (var i = from; i < to; i += step) result.push(i); else for (var i = from; i > to; i += step) result.push(i); return result; } // TODO: ForEach, Select etc. for object (passing both key and value into inner func) // TODO: Enumerable.Range with optional "from" and "step" parameters // TODO: Working with Sets - that are objects with any values, where only keys have sense, hence could be used like: if (a in Set(1, 4, 5, 8)) { ... }