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
@*/
Ox.every = function(col, fn) {
return Ox.filter(Ox.values(col), fn || function(v) {
return v;
}).length == Ox.len(col);
return Ox.filter(Ox.values(col), fn || Ox.identity).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 != ' '; })
'foobar'
@*/
Ox.filter = function(col, fn) {
var type = Ox.typeOf(col),
ret = type == 'array' ? [] : type == 'object' ? {} : '';
Ox.forEach(col, function(val, key) {
if (fn(val, key)) {
if (type == 'array') {
ret.push(val);
} else if (type == 'object') {
ret[key] = val;
} else {
ret += val;
Ox.filter = function(col, fn, that) {
var ret, type = Ox.typeOf(col);
if (type == 'object') {
ret = {};
Ox.forEach(col, function(val, key) {
if (fn.call(that, val, key, col)) {
ret[val] = key;
}
});
} else {
ret = Ox.toArray(col).filter(fn, that);
if (type == 'string') {
ret = ret.join('');
}
});
}
return ret;
};
@ -169,82 +168,60 @@ Ox.forEach <f> forEach loop
> Ox.test.string
"012abcfoo"
@*/
// fixme: see http://stackoverflow.com/questions/2641347/javascript-array-foreach-howto-break
// maybe throwing an exception (Ox.break()?) is better than returning false
Ox.forEach = function(col, fn, includePrototype) {
var ind = 0, isObject = Ox.isObject(col), key;
// Safari will not loop through an arguments array
col = Ox.isArguments(col) ? Ox.toArray(col) : col;
for (key in col) {
key = isObject ? key : parseInt(key);
// fixme: fn.call(context, obj[key], key, obj) may be more standard...
if ((
includePrototype || Object.hasOwnProperty.call(col, key)
) && fn(col[key], key, ind++) === false) {
break;
Ox.forEach = function(col, fn, that) {
var i, key, type = Ox.typeOf(col);
if (type != 'array' && type != 'object') {
col = Ox.toArray(col);
}
try {
if (type == 'object') {
for (key in col) {
// Ox.hasOwn(obj, key) && fn.call(that, col[key], key, col);
if (Ox.hasOwn(col, key) && fn.call(that, col[key], key, col) === false) {
console.warn('Returning false in Ox.forEach is deprecated.')
break;
}
}
} else {
for (i = 0; i < col.length; i++) {
// fn.call(that, col[i], i, col);
if (fn.call(that, col[i], i, col) === false) {
console.warn('Returning false in Ox.forEach is deprecated.')
break;
}
}
}
} catch(e) {
if (e !== Ox.BreakError) {
throw e;
}
}
return col;
};
/*@
Ox.getIndex <f> Returns the first array index of an object where obj[key] is val
> Ox.getIndex([{a: 1}, {a: 2}, {a: 1}], 'a', 2)
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;
return type == 'object' ? key : i;
};
/*@
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')
0
> Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar')
1
> Ox.getIndexById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
-1
@*/
Ox.getIndexById = function(arr, id) {
// FIXME: shouldn't this be merged into Ox.getIndex?
return Ox.getIndex(arr, '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 Ox.indexOf(arr, function(obj) {
return obj.id === id;
});
return ret;
};
/*@
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')
{id: "foo", str: "Foo"}
> Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'bar')
{id: "bar", str: "Bar"}
> Ox.getObjectById([{id: 'foo', str: 'Foo'}, {id: 'bar', str: 'Bar'}], 'baz')
null
@*/
Ox.getObjectById = function(arr, id) {
// FIXME: shouldn't this be merged into Ox.getObject?
return Ox.getObject(arr, 'id', id);
var index = Ox.getIndexById(arr, id);
return index > -1 ? arr[index] : null;
};
/*@
@ -309,6 +286,20 @@ Ox.getset = function(obj, args, callback, context) {
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
(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
Unlike <code>foobarbaz[foobarbaz.length - 1]</code>,
<code>Ox.last(foobarbaz)</code> is short.
Unlike <code>arrayWithALongName[arrayWithALongName.length - 1]</code>,
<code>Ox.last(arrayWithALongName)</code> is short.
<script>
Ox.test.array = [1, 2, 3];
</script>
@ -372,6 +363,8 @@ Ox.last <f> Gets or sets the last element of an array
[1, 2, 4]
> Ox.test.array
[1, 2, 4]
> Ox.last('123')
'3'
@*/
Ox.last = function(arr, val) {
var ret;
@ -449,14 +442,14 @@ Ox.makeObject <f> Takes an array and returns an object
> (function() { return Ox.makeObject(arguments); }())
{}
@*/
Ox.makeObject = function(obj) {
var ret = {};
if (Ox.isObject(obj[0])) {
Ox.makeObject = function(arr) {
var ret = {}, type = Ox.typeOf(arr[0]);
if (type == 'object') {
// ({foo: 'bar'})
ret = obj[0];
} else if (obj.length) {
ret = arr[0];
} else if (type == 'string') {
// ('foo', 'bar')
ret[obj[0]] = obj[1]
ret[arr[0]] = arr[1];
}
return ret;
};
@ -506,7 +499,15 @@ Ox.max <f> Returns the maximum value of a collection
3
@*/
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
@*/
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,
objects and strings.
> 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
> Ox.some("foo", function(v) { return v == 'f'; })
true
> Ox.some([false, 0, null, '', void 0])
> Ox.some([false, null, 0, '', void 0])
false
@*/
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
Alias for <code>Array.prototype.slice.call</code>
(value) -> <a> True array
value <*> Array-like object
> (function() { return Ox.toArray(arguments); }("foo", "bar"))
@ -711,12 +728,18 @@ Ox.values <f> Returns the values of a collection
[1, 3]
@*/
Ox.values = function(col) {
// Ox.values(str) is identical to str.split('')
var values = [];
Ox.forEach(col, function(val) {
values.push(val);
});
return values;
var ret, type = Ox.typeOf(col);
if (type == 'array') {
ret = col;
} else if (type == 'object') {
ret = [];
Ox.forEach(col, function(val) {
ret.push(val);
});
} else if (type == 'string') {
ret = col.split('');
}
return ret;
};
/*@