in Ox.every, use Ox.identity; faster Ox.filter; in Ox.forEach, allow for Ox.break, and use standard arguments for iterator function, remove Ox.getIndex and Ox.getObject; add Ox.indexOf; in Ox.makeObject, use Ox.typeOf; make sure Ox.max and Ox.min don't blow the stack; add Ox.slice; in Ox.values, use Ox.typeOf

This commit is contained in:
rolux 2012-05-21 22:17:33 +02:00
parent bfa9394850
commit 3d4a79b6a2

View file

@ -92,9 +92,7 @@ Ox.every <f> Tests if every element of a collection satisfies a given condition
true true
@*/ @*/
Ox.every = function(col, fn) { Ox.every = function(col, fn) {
return Ox.filter(Ox.values(col), fn || function(v) { return Ox.filter(Ox.values(col), fn || Ox.identity).length == Ox.len(col);
return v;
}).length == Ox.len(col);
}; };
/*@ /*@
@ -108,20 +106,21 @@ Ox.filter <f> Filters a collection by a given condition
> Ox.filter(' foo bar ', function(v) { return v != ' '; }) > Ox.filter(' foo bar ', function(v) { return v != ' '; })
'foobar' 'foobar'
@*/ @*/
Ox.filter = function(col, fn) { Ox.filter = function(col, fn, that) {
var type = Ox.typeOf(col), var ret, type = Ox.typeOf(col);
ret = type == 'array' ? [] : type == 'object' ? {} : ''; if (type == 'object') {
ret = {};
Ox.forEach(col, function(val, key) { Ox.forEach(col, function(val, key) {
if (fn(val, key)) { if (fn.call(that, val, key, col)) {
if (type == 'array') { ret[val] = key;
ret.push(val);
} else if (type == 'object') {
ret[key] = val;
} else {
ret += val;
}
} }
}); });
} else {
ret = Ox.toArray(col).filter(fn, that);
if (type == 'string') {
ret = ret.join('');
}
}
return ret; return ret;
}; };
@ -169,82 +168,60 @@ Ox.forEach <f> forEach loop
> Ox.test.string > Ox.test.string
"012abcfoo" "012abcfoo"
@*/ @*/
// fixme: see http://stackoverflow.com/questions/2641347/javascript-array-foreach-howto-break Ox.forEach = function(col, fn, that) {
// maybe throwing an exception (Ox.break()?) is better than returning false var i, key, type = Ox.typeOf(col);
Ox.forEach = function(col, fn, includePrototype) { if (type != 'array' && type != 'object') {
var ind = 0, isObject = Ox.isObject(col), key; col = Ox.toArray(col);
// Safari will not loop through an arguments array }
col = Ox.isArguments(col) ? Ox.toArray(col) : col; try {
if (type == 'object') {
for (key in col) { for (key in col) {
key = isObject ? key : parseInt(key); // Ox.hasOwn(obj, key) && fn.call(that, col[key], key, col);
// fixme: fn.call(context, obj[key], key, obj) may be more standard... if (Ox.hasOwn(col, key) && fn.call(that, col[key], key, col) === false) {
if (( console.warn('Returning false in Ox.forEach is deprecated.')
includePrototype || Object.hasOwnProperty.call(col, key)
) && fn(col[key], key, ind++) === false) {
break; break;
} }
} }
return col; } else {
}; for (i = 0; i < col.length; i++) {
// fn.call(that, col[i], i, col);
/*@ if (fn.call(that, col[i], i, col) === false) {
Ox.getIndex <f> Returns the first array index of an object where obj[key] is val console.warn('Returning false in Ox.forEach is deprecated.')
> Ox.getIndex([{a: 1}, {a: 2}, {a: 1}], 'a', 2) break;
1
> Ox.getIndex([{a: 1}, {a: 2}, {a: 1}], 'a', 1)
0
> Ox.getIndex([{a: 1}, {a: 2}, {a: 1}], 'a', 0)
-1
@*/
Ox.getIndex = function(arr, key, val) {
var ret = -1;
Ox.forEach(arr, function(obj, ind) {
if (obj[key] === val) {
ret = ind;
return false;
} }
}); }
return ret; }
} catch(e) {
if (e !== Ox.BreakError) {
throw e;
}
}
return type == 'object' ? key : i;
}; };
/*@ /*@
Ox.getIndexById <f> Returns the first array index of an object with a given id Ox.getIndexById <f> Returns the first array index of an object with a given id
> Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'foo') > Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar')
0 1
> Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
-1
@*/ @*/
Ox.getIndexById = function(arr, id) { Ox.getIndexById = function(arr, id) {
// FIXME: shouldn't this be merged into Ox.getIndex? return Ox.indexOf(arr, function(obj) {
return Ox.getIndex(arr, 'id', id); return obj.id === id;
};
/*@
Ox.getObject <f> Returns the first object in an array where obj[key] is val
> Ox.getObject([{a: 1, i: 0}, {a: 2, i: 1}, {a: 1, i: 2}], 'a', 2)
{a: 2, i: 1}
> Ox.getObject([{a: 1, i: 0}, {a: 2, i: 1}, {a: 1, i: 2}], 'a', 1)
{a: 1, i: 0}
> Ox.getObject([{a: 1, i: 0}, {a: 2, i: 1}, {a: 1, i: 2}], 'a', 0)
null
@*/
Ox.getObject = function(arr, key, val) {
var ret = null;
Ox.forEach(arr, function(obj) {
if (obj[key] === val) {
ret = obj;
return false;
}
}); });
return ret;
}; };
/*@ /*@
Ox.getObjectById <f> Returns the first object in an array with a given id Ox.getObjectById <f> Returns the first object in an array with a given id
> Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'foo') > Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar')
{id: "foo", str: "Foo"} {id: "bar", str: "Bar"}
> Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
null
@*/ @*/
Ox.getObjectById = function(arr, id) { Ox.getObjectById = function(arr, id) {
// FIXME: shouldn't this be merged into Ox.getObject? var index = Ox.getIndexById(arr, id);
return Ox.getObject(arr, 'id', id); return index > -1 ? arr[index] : null;
}; };
/*@ /*@
@ -309,6 +286,20 @@ Ox.getset = function(obj, args, callback, context) {
return ret; return ret;
} }
/*@
Ox.indexOf <f> <code>indexOf</code> with a test function
> Ox.indexOf([1, 2, 3], function(val) { return val % 2 == 0; })
1
> Ox.indexOf('fooBar', function(val) { return val == val.toUpperCase(); })
3
@*/
Ox.indexOf = function(col, fn) {
var index = Ox.forEach(col, function(val) {
fn(val) && Ox.break();
});
return index == col.length ? -1 : index;
};
/*@ /*@
Ox.isEmpty <f> Tests if a value is an empty array, object or string Ox.isEmpty <f> Tests if a value is an empty array, object or string
(value) -> <b> True if the value is an empty array, object or string (value) -> <b> True if the value is an empty array, object or string
@ -361,8 +352,8 @@ Ox.keys = function(obj) {
/*@ /*@
Ox.last <f> Gets or sets the last element of an array Ox.last <f> Gets or sets the last element of an array
Unlike <code>foobarbaz[foobarbaz.length - 1]</code>, Unlike <code>arrayWithALongName[arrayWithALongName.length - 1]</code>,
<code>Ox.last(foobarbaz)</code> is short. <code>Ox.last(arrayWithALongName)</code> is short.
<script> <script>
Ox.test.array = [1, 2, 3]; Ox.test.array = [1, 2, 3];
</script> </script>
@ -372,6 +363,8 @@ Ox.last <f> Gets or sets the last element of an array
[1, 2, 4] [1, 2, 4]
> Ox.test.array > Ox.test.array
[1, 2, 4] [1, 2, 4]
> Ox.last('123')
'3'
@*/ @*/
Ox.last = function(arr, val) { Ox.last = function(arr, val) {
var ret; var ret;
@ -449,14 +442,14 @@ Ox.makeObject <f> Takes an array and returns an object
> (function() { return Ox.makeObject(arguments); }()) > (function() { return Ox.makeObject(arguments); }())
{} {}
@*/ @*/
Ox.makeObject = function(obj) { Ox.makeObject = function(arr) {
var ret = {}; var ret = {}, type = Ox.typeOf(arr[0]);
if (Ox.isObject(obj[0])) { if (type == 'object') {
// ({foo: 'bar'}) // ({foo: 'bar'})
ret = obj[0]; ret = arr[0];
} else if (obj.length) { } else if (type == 'string') {
// ('foo', 'bar') // ('foo', 'bar')
ret[obj[0]] = obj[1] ret[arr[0]] = arr[1];
} }
return ret; return ret;
}; };
@ -506,7 +499,15 @@ Ox.max <f> Returns the maximum value of a collection
3 3
@*/ @*/
Ox.max = function(col) { Ox.max = function(col) {
return Math.max.apply(Math, Ox.values(col)); var ret, values = Ox.values(col);
if (values.length < Ox.STACK_LENGTH) {
ret = Math.max.apply(null, values)
} else {
ret = values.reduce(function(pre, val) {
return Math.max(pre, val);
}, -Infinity);
}
return ret;
}; };
/*@ /*@
@ -519,7 +520,15 @@ Ox.min <f> Returns the minimum value of a collection
1 1
@*/ @*/
Ox.min = function(col) { Ox.min = function(col) {
return Math.min.apply(Math, Ox.values(col)); var ret, values = Ox.values(col);
if (values.length < Ox.STACK_LENGTH) {
ret = Math.min.apply(null, values)
} else {
ret = values.reduce(function(pre, val) {
return Math.min(pre, val);
}, Infinity);
}
return ret;
}; };
/*@ /*@
@ -595,7 +604,16 @@ Ox.shuffle = function(col) {
}; };
/*@ /*@
Ox.some <f> Tests if one or more elements of a collection satisfy a given condition Ox.slice <f> Alias for <code>Array.prototype.slice.call</code>
> (function() { return Ox.slice(arguments, 1, -1); }(1, 2, 3))
[2]
@*/
Ox.slice = function(val, start, stop) {
return Array.prototype.slice.call(val, start, stop);
};
/*@
Ox.some <f> Tests if one or more elements of a collection meet a given condition
Unlike <code>[].some()</code>, <code>Ox.some()</code> works for arrays, Unlike <code>[].some()</code>, <code>Ox.some()</code> works for arrays,
objects and strings. objects and strings.
> Ox.some([2, 1, 0], function(i, v) { return i == v; }) > Ox.some([2, 1, 0], function(i, v) { return i == v; })
@ -604,7 +622,7 @@ Ox.some <f> Tests if one or more elements of a collection satisfy a given condit
true true
> Ox.some("foo", function(v) { return v == 'f'; }) > Ox.some("foo", function(v) { return v == 'f'; })
true true
> Ox.some([false, 0, null, '', void 0]) > Ox.some([false, null, 0, '', void 0])
false false
@*/ @*/
Ox.some = function(obj, fn) { Ox.some = function(obj, fn) {
@ -670,7 +688,6 @@ Ox.sum = function(col) {
/*@ /*@
Ox.toArray <f> Takes an array-like object and returns a true array Ox.toArray <f> Takes an array-like object and returns a true array
Alias for <code>Array.prototype.slice.call</code>
(value) -> <a> True array (value) -> <a> True array
value <*> Array-like object value <*> Array-like object
> (function() { return Ox.toArray(arguments); }("foo", "bar")) > (function() { return Ox.toArray(arguments); }("foo", "bar"))
@ -711,12 +728,18 @@ Ox.values <f> Returns the values of a collection
[1, 3] [1, 3]
@*/ @*/
Ox.values = function(col) { Ox.values = function(col) {
// Ox.values(str) is identical to str.split('') var ret, type = Ox.typeOf(col);
var values = []; if (type == 'array') {
ret = col;
} else if (type == 'object') {
ret = [];
Ox.forEach(col, function(val) { Ox.forEach(col, function(val) {
values.push(val); ret.push(val);
}); });
return values; } else if (type == 'string') {
ret = col.split('');
}
return ret;
}; };
/*@ /*@