Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

array-extras adds set methods #299

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions src/collection/js/array-extras.js
Original file line number Diff line number Diff line change
Expand Up @@ -393,3 +393,177 @@ A.flatten = function(a) {

return result;
};

/**
Intersection of two or more arrays.

Note that the return value may contain duplicate values - you
will need to use Y.Array.unique(returnedArray, comparisonFunction). This
is because there's no prior reason that the comparison function used
to determine the intersection should also be used as the equality function
when determining uniqueness of values (although you're into the edge cases
where they're not).

@method intersect
@param {Array} arr1 First array
@param {Array} arr2* Second array to compare with the first
@param {Function} [comparison] Comparison function (optional). If not passed,
intersect will use indexOf tests (which should do strict === comparison).
If a function is passed, it will be used to compare the items in the
arrays. This function will receive two arguments:
@param {Any} comparison.item1 An item from the first array arr1
@param {Any} comparison.item2 An item from the second array. This
@return {Array} Array of items that appear in both original arrays.
@static
@since 3.7.3
**/
A.intersect = function (arr1, arr2, comparison) {
var i = 0,
args,
a1,
a2,
len1 = 0,
ret = [],
iO = A.indexOf,
fn;

if (comparison && L.isFunction(comparison)) {

fn = function (item) {
var i;
for (i = 0; i < a2.length; i = i + 1) {
if (comparison(item, a2[i])) {
ret.push(item, a2[i]);
}

}
};

} else {

fn = function (item) {
if (iO(a2, item) !== -1) {
ret.push(item);
}
};
}

a1 = A(arr1);
a2 = A(arr2);
len1 = a1.length;

args = A(arguments);

// we've got more than two arrays:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Upon re-reading the doc comments above, I now see that the description mentions this method accepts "two or more" arrays, but that wasn't obvious at first because the parameters aren't documented properly to indicate that. Instead of explicitly documenting two array params, use a splat argument like @param {Array} a* One or more arrays..

See http://yui.github.com/yuidoc/syntax/index.html#param

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, sorry, just going through exact same thought process! Also are you able to help me understand why Travis failed? https://travis-ci.org/#!/yui/yui3/jobs/2712349 I thought the build process would add these from the src to the build but it looks like they haven't? What have I missed?

Thank you!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like my build script didn't pick up the Travis Env. I'll look into it in a bit.

if ((args.length === 3 && !L.isFunction(comparison)) ||
(args.length > 3)) {
// intersection of the first two:
if (L.isFunction(args[args.length - 1])) {
ret = A.intersect(a1, a2, args[args.length - 1]);
} else {
ret = A.intersect(a1, a2);
}
// replace the first two with their intersection
args.splice(0, 2, ret);
// rinse and repeat
return A.intersect.apply(this, args);

}

for (i = 0; i < len1; i = i + 1) {
fn(a1[i]);
}


return ret;

};

/**
Returns union of two or more arrays, with duplicates removed

@method union
@param {Array} arr1 First array
@param {Array} arr2* Second (or more) array to combine with the first
@param {Function} [comparison] Comparison function to be used in call to unique (optional)
@return {Array}
@static
@since 3.7.3
**/
A.union = function (arr1, arr2, comparison) {

var args = A(arguments),
a1 = A(arr1),
a2 = A(arr2),
a3;

// more than 2 arrays passed: do the first two and then recurse.
if (args.length > 2 && !L.isFunction(comparison)) {
a3 = A.union(arr1, arr2);
args.splice(0, 2, a3);
return A.union.apply(this, args);
}

// set up arguments for call to apply:
a2.unshift(a1.length, 0);
a1.splice.apply(a1, a2);


return A.unique(a1, comparison);
};

/**
Calculates the difference between two arrays: that is, the values in arr1
that are not contained in arr2.

@method diff
@param {Array} arr1 First array
@param {Array} arr2 Second array
@param {Function} [comparison] Function used to tell if two items are equal.
The function will receive two arguments:
@param comparison.item1 The value from the first array
@param comparison.item2 A value from the second array to compare to.
The comparison function is optional; if not passed, A.indexOf will be used.
If the function returns true they are the same.
@return {Array}
@static
@since 3.7.3
**/
A.diff = function (arr1, arr2, comparison) {

var i = 0,
ret = [],
a1,
a2,
cb,
iO = A.indexOf,
fn = (comparison && L.isFunction(comparison)) ?
comparison :
false;


a1 = A(arr1);
a2 = A(arr2);

if (fn) {

cb = function (a) { return fn(a1[i], a); };

for (i = 0; i < a1.length; i = i + 1) {

if (A.find(a2, cb) === null) {
ret.push(a1[i]);
}

}
} else {
for (i = 0; i < a1.length; i = i + 1) {

if (iO(a2, a1[i]) === -1) {
ret.push(a1[i]);
}

}
}
return ret;
};
Loading