Here's a question:
What would the best way be, using Link, to remove all items from an array that have a specific value for certain properties?
Link works on a "copy" (not really, but it generates a copy as it works) of the array, so unfortunately it doesn't do any destructive changes. It's both a blessing and a curse depending on who you ask. So I'm a bit torn on that part of it right now since I myself am struggling with the concept of efficiently removing items. I might add in something like that, it may not be common to such libraries like Lazy, but you and me, seem to need it - since it's good for games.
Now, to delete things we can do this:
// figures out what to delete, by populating an array of true/false values.
function deletable(a, b) {
if (b needs deletion) a.push(true);
else a.push(false);
return a;
}
// runs the query:
var items = Link(array).reduce(deletable, []);
// performs the deletions:
for (var i = 0; i < items.length; ++i) { if (items[i]) { array.splice(i, 1); i--; } }
We need to figure out what to delete before we delete it, because deleting things as the query runs destroys it's stopping condition and can muddle up results. To do it I use reduce: reduce is used to create something. It takes two inputs from the original array and turns them into a single output (effectively reducing the size), however if you start it off with an array or object, we can do interesting things with values on an as-they-are-seen basis. The bad thing is we are effectively traversing the entire source array twice, which is no-good performance wise.
Also, notice there is no filter clause. It might be better to filter things out before calling reduce, but then you are working off a modified version of the array... a filtered version of it to be precise. So it'll tell you nothing as to where to snip an item out, sadly. (again hence the speed).
Ok... I convinced myself removing items is really terrible in these kinds of schemes... I can try to figure out deletion, but it get's tricky in the whole lazy-execution scheme. It might be doable, though.
Also, in my experience Array.splice is terribly, terribly slow. It turns out recreating a new array is better. Hmm...
// populates an array with items that are okay to keep:
function deleted(a, b) {
if (b does not need deletion) a.push(b);
return a;
}
// runs the query:
array = Link(array).reduce(deleted, []);
The above might be faster if you are okay with replacing the original array with an entirely new one! (This now sounds more like a reduce-y type of thing to do).
In fact it get's
even faster if we continue this line of thought:
// runs the query:
array = Link(array).where(what-to-delete).toArray();
Now it'll be flying... Esp. if it's an array of objects. Since it doesn't need to recreate the objects, recreating an array is a low-cost alternative to hand-picking items to remove. It may in fact be the best solution, and what Link would do internally, anyways.
If you want to remove a single item... or only a few, we can do this:
var bob = { name: "bob", dead: false };
var array = [bob, { name: "sue", dead: true }, { name: "ann", dead: false }, { name: "tom", dead: true }];
// runs the query:
array.splice(Link(array).indexOf(bob), 1); // straight-up removal.
// bob is now removed
// or use a new feature:
array.splice(Link(array).indexOf("dead", true), 1); // deletes an object with the first property of "dead" set to true.
// sue is now removed
// alternative, for deleting several items (also the safest solution since it doesn't assume the object is in the list):
var i;
while (i = Link(array).indexOf("dead", true) >= 0) { array.splice(i, 1); }
// sue and tom are now removed.
So there, I think I exhausted many possibilities!
It seems that uniq() likes to trim out objects that aren't actually duplicates (either by content or identity), too.
uniq is still a WIP, it filters out identical strings, and numbers only. I'll have to look into how other libraries do it. It might be cheating, but if the uniq doesn't work as other standard libraries do, it can mean bad things. I'm sure there is a good, general, algorithm somewhere. That said my current approach is not too bad, just a super-lite version of the real deal.
So, my current to-do list:
1. Implement skip()
2. Implement a destructive API - there may be no need...
3. Improve reduce
4. Improve uniq