Is there an equivalent of IEnumerable.Any(Predicate<T>) in JavaScript or jQuery?
I am validating a list of items, and want to break early if error is detected. I could do it using $.each, but I need to use an external flag to see if the item was actually found:
var found = false;
$.each(array, function(i) {
if (notValid(array[i])) {
found = true;
}
return !found;
});
What would be a better way? I don't like using plain for with JavaScript arrays because it iterates over all of its members, not just values.
These days you could actually use Array.prototype.some (specced in ES5) to get the same effect:
array.some(function(item) {
return notValid(item);
});
You could use variant of jQuery is function which accepts a predicate:
$(array).is(function(index) {
return notValid(this);
});
Xion's answer is correct. To expand upon his answer:
jQuery's .is(function) has the same behavior as .NET's IEnumerable.Any(Predicate<T>).
From http://docs.jquery.com/is:
Checks the current selection against an expression and returns true, if at least one element of the selection fits the given expression.
You should use an ordinary for loop (not for ... in), which will only loop through array elements.
You might use array.filter (IE 9+ see link below for more detail)
[].filter(function(){ return true|false ;}).length > 0;
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
I would suggest that you try the JavaScript for in loop. However, be aware that the syntax is quite different than what you get with a .net IEnumerable. Here is a small illustrative code sample.
var names = ['Alice','Bob','Charlie','David'];
for (x in names)
{
var name = names[x];
alert('Hello, ' + name);
}
var cards = { HoleCard: 'Ace of Spades', VisibleCard='Five of Hearts' };
for (x in cards)
{
var position = x;
var card = card[x];
alert('I have a card: ' + position + ': ' + card);
}
I suggest you to use the $.grep() method. It's very close to IEnumerable.Any(Predicate<T>):
$.grep(array, function(n, i) {
return (n == 5);
});
Here a working sample to you: http://jsfiddle.net/ErickPetru/BYjcu/.
2021 Update
This answer was posted more than 10 years ago, so it's important to highlight that:
When it was published, it was a solution that made total sense, since there was nothing native to JavaScript to solve this problem with a single function call at that time;
The original question has the jQuery tag, so a jQuery-based answer is not only expected, it's a must. Down voting because of that doesn't makes sense at all.
JavaScript world evolved a lot since then, so if you aren't stuck with jQuery, please use a more updated solution! This one is here for historical purposes, and to be kept as reference for old needs that maybe someone still find useful when working with legacy code.
Necromancing.
If you cannot use array.some, you can create your own function in TypeScript:
interface selectorCallback_t<TSource>
{
(item: TSource): boolean;
}
function Any<TSource>(source: TSource[], predicate: selectorCallback_t<TSource> )
{
if (source == null)
throw new Error("ArgumentNullException: source");
if (predicate == null)
throw new Error("ArgumentNullException: predicate");
for (let i = 0; i < source.length; ++i)
{
if (predicate(source[i]))
return true;
}
return false;
} // End Function Any
Which transpiles down to
function Any(source, predicate)
{
if (source == null)
throw new Error("ArgumentNullException: source");
if (predicate == null)
throw new Error("ArgumentNullException: predicate");
for (var i = 0; i < source.length; ++i)
{
if (predicate(source[i]))
return true;
}
return false;
}
Usage:
var names = ['Alice','Bob','Charlie','David'];
Any(names, x => x === 'Alice');
Related
Hey guys I am trying trying to right this javascript code into c++. I am doing quick sort and everything is straight forward minus the last step.
function quickSort(arr)
{
//base case if the arr is 1 or 0 then return the array
if(arr.length === 1 || arr.length === 0)
{
return arr;
}
var pivotIndex = Math.floor(arr.length/2);
var pivotValue = arr[pivotIndex];
var before = [];
var after = [];
for(var counter = 0; counter < arr.length; counter++)
{
if(counter === pivotIndex)
continue;
if(pivotValue <= arr[counter])
{
before.push(arr[counter])
}
else
{
after.push(arr[counter])
}
}
//this step I am having trouble rewriting in c++
return quickSort(after).concat(pivotValue).concat(quickSort(before));
}
I am having a hard time rewriting the recursive step in c++. I am not sure how concat 2 vector. I tried using the insert method but I keep getting an error about invalid use of void expression.
vector<int> quickSort(vector<int> arr)
{
if(arr.size() == 1 || arr.size() == 0)
{
return arr;
}
int pivotIndex = arr.size()/2;
int pivotValue = arr[pivotIndex];
vector<int> before;
vector<int> after;
//put values in before or after the piv
for(size_t counter = 0; counter < arr.size(); counter++)
{
if(counter == pivotIndex)
continue;
if(pivotValue <= arr[counter])
before.push_back( arr[counter]);
else
after.push_back( arr[counter]);
}
return //????? not sure how to do this
}
So, you realized that your core question was "how to concatenate two vectors", and you found a right answer: using insert. Now your question is about why you were getting "an error about invalid use of void expression." (That's the assumption my answer is for, at least.)
That's because you were likely trying to do something like the following:
return quickSort(after).insert( /* stuff */ );
which is wrong. In JavaScript, array.concat returns the concatenated array. It's return type is effectively Array, and so doing return arr.concat(arr2) returns an Array because arr.concat would return an Array. Further, in JavaScript, array.concat doesn't modify the array it was called on, but rather returns a new array.
In C++, however, vector.insert (#4 in the reference) returns void. That means it returns nothing. So when you try to return the result of insert, you get that error about invalid use of a void expression. Further, in C++, vector.insert does modify the vector it was called on.
So how do you use insert in this case?
vector<int> quickSort(vector<int> arr)
{
// ...
// Sort `before` and `after`
before = quickSort(before);
after = quickSort(after);
// Modify `after` and return it.
after.push_back(pivotValue);
after.insert(after.end(), before.begin(), before.end());
return after;
}
Note: My code isn't optimal and the idea of rewriting JS in C++ is also oddly specific. My answer is to simply outline the problem asked in the question, not to give a good C++ implementation of quick sort.
To concat two vector , you can use std::merge
like:std::merge(v1.begin(), v1.end(), v2.begin(), v2.end(), std::back_inserter(dst));
This is my first question, so I apologize if this isn't formatted correctly or placed in the proper area.
I just completed the FreeCodeCamp checking for palindromes challenge. I can't help but think my solution was very inelegant.
function palindrome(str) {
var cleanString = str.replace(/[^A-Za-z0-9]/g, '');
var lowerCleanString = cleanString.toLowerCase();
var lowerArr = lowerCleanString.split('');
var reverseArr = lowerArr.reverse();
var joinedArr = reverseArr.join('');
if (joinedArr === lowerCleanString) {
return true;
}
// Good luck!
else {
return false;
}
}
I know it worked, but is it possible to do some of these steps together or in a cleaner way?
Simple function to check for palindromes
function checkPalindrome(palindrome) {
return palindrome == palindrome.split('').reverse().join('');
}
function palindrome(str) {
var newstr = str.replace(/[\W_]/g,'').toLowerCase();
if(newstr === newstr.split('').reverse().join('')){
return true;
}
return false;
}
palindrome("five|\_/|four");
You can use many methods in one row like I've used them .It's more simple :)
Good luck
Wow, I really like the answers comparing the string to a string.split('').reverse().join('') version of itself. I didn't think about that. Forgot about the .reverse() function. I ended up processing the string and splitting it out into an array and then using a double counter for the loop to compare the first and last items in the array. Was kinda fun to learn how to do that, but I like the .reverse() function use better.
In case someone is curious about the for loop I used ...
for(let i = 0, j = arr.length-1; i < j; i++, j--) {
if (arr[i] !== arr[j]) {
return false;
}
}
I tried to find out some good examples but SO seems to have mainly examples from 4-5 years ago and I would like to use a solution that would work using modern browser capabilities.
Ihave an array of test objects:
var tests;
Each test object contains a testId.
How can I remove test object with testId = 25 from the array tests. I was thinking of a for loop but is there a cleaner way to do this?
The best answer depends on whether you know in advance whether there's at most one match, or potentially more than one (and in the latter case whether you want to remove all of them or just the first)
Removing all matches
The "simplest" way is to use filter, although strictly that produces a new array without the matching element:
tests = tests.filter(function(e) {
return e.testId !== 25;
});
This is OK, unless other code is holding a reference to the original array.
Modifying the array safely "in-place" still appears to require a combination of a for loop with .splice:
for (var i = 0; i < tests.length; ) { // nb: deliberate .length test
if (tests[i].testId === 25) {
tests.splice(i, 1);
} else {
++i;
}
}
The "safely" caveat is because the functional methods of iterating through an entire array will get confused if the current element in the array is removed. That is not a concern in the "first match" methods shown below.
Removing first (or only) match
The plain for method is still pretty simple (and probably most efficient, too!)
for (var i = 0, n = tests.length; i < n; ++i) {
if (tests[i].testId === 25) {
tests.splice(i, 1);
break;
}
}
The .some method per Johan's answer can iterate through an array and then exit on first match (although some may object on philosophical grounds to a boolean predicate function also mutating the array):
var didRemove = tests.some(function(e, i, a) {
if (e.testId === 25) {
a.splice(i, 1);
return true; // causes the loop to exit
}
});
In ES6-draft there's .findIndex, which is a generalisation of .indexOf:
var index = tests.findIndex(function(e) {
return e.testId === 25;
});
if (index >= 0) {
tests.splice(index, 1);
}
One way is to loop through all objects and splice a matching object out of the array.
Instead of forEach I use some (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some). Because with the some method you can "break" the loop by returning true so that you don't need to go through all objects if a match has been found.
tests.some(function(testObject, index) {
if (testObject.testId === 25) {
tests.splice(index, 1);
return true;
}
});
Or wrap it in a function
var removeObjectById = function(id) {
tests.some(function(testObject, index) {
if (testObject.testId === id) {
tests.splice(index, 1);
return true;
}
});
}
removeObjectById(25)
I'm new to javascript and still coming to terms with the language's nuances.
I have a piece of code where I have to check a set of conditions on a particular variable.
if (a=="MAIN_DOMAINNAME" || a=="DOMAIN_SERIAL" || a=="DOMAIN_REFRESH" || a=="DOMAIN_RETRY" || a=="DOMAIN_EXPIRE" || a=="DOMAIN_NEGTTL" || a=="MAIN_NS") {
Is there a better way to do this conditional check, like say:
if a is one of ("DOMAIN_SERIAL", "MAIN_DOMAINNAME", "DOMAIN_REFRESH" ) {?
Assuming a relatively modern browser, you can use Array.indexOf (spec)
if (["DOMAIN_SERIAL", "MAIN_DOMAINNAME", "DOMAIN_REFRESH"].indexOf(a) !== -1)
Note - you can easily shim it for older browsers (see the mdn link on how).
A regex would be shorter and works everywhere :
if ( /^(MAIN_DOMAINNAME|DOMAIN_SERIAL|DOMAIN_REFRESH|..)$/.test(a) ) {
// do stuff
}
FIDDLE
var ars = ["DOMAIN_SERIAL", "MAIN_DOMAINNAME", "DOMAIN_REFRESH"];
if(ars.some(function(ar){ return a === ar; })){
// do smth
}
Should mention the switch statement as it should be working fine with the example given in the question.
switch(a) {
case('MAIN_DOMAINAME'):
case('DOMAIN_SERIAL'):
case('DOMAIN_REFRESH'):
case('DOMAIN_RETRY'):
console.log('Go wild.');
break;
}
Not as lightweight as the other answers, but it's readable and matches (a === b).
I prefer the regex solution already provided by adeneo, but if you want something that matches the
if a is one of (...
wording from the question reasonably closely you can do this:
if (a in list("MAIN_DOMAINNAME", "DOMAIN_SERIAL", "DOMAIN_REFRESH", "DOMAIN_RETRY")) {
// do something (rest of list omitted to avoid scrolling)
}
by providing a helper function to turn the list into an object:
function list() {
var o={}, i;
for (i=0; i < arguments.length; i++) o[arguments[i]] = true;
return o;
}
Of course you can omit the helper function and just use an object literal, but that's ugly:
if (a in {"MAIN_DOMAINNAME":1, "DOMAIN_SERIAL":1, "DOMAIN_REFRESH":1}) {
I'm writing a custom sort function that I'm prototyping into Array. (PLEASE don't post answers explaining to me how I shouldn't bother prototyping into Array for whatever reason you feel prototyping into Array isn't a good idea).
so, my method looks like this:
//method
Array.prototype.mySort = function(memberName, ascOrDesc){
var labelRow = this.shift();
var ret = this.sort((function (a,b){
if(ascOrDesc > 0)
return (a[memberName] > b[memberName])?1:-1;
return (a[memberName] < b[memberName])?1:-1;
}));
ret.unshift(labelRow)
return ret;
}
Notice how this.shift() will affect the Array IN PLACE.
However, I'm not clear on how this is accomplished. If I wanted to write my own myShift method, at some point I'd need to say something to the effect of
this = this.myShift();
which is obviously illegal.
So, I'm trying to understand how shift() gets access to the array's members and is able to remove the first one in-place. And if I'm allowed to do something analogous, or if this is somehow baked in and not available to me to use.
You can access the array using this inside the method.
You can for example implement the shift method as:
Array.prototype.myShift = function() {
if (this.length == 0) return null;
var result = this[0];
for (var i = 1; i < this.length; i++) {
this[i-1] = this[i];
}
this.length--;
return result;
};
The problem is that you can't assign to this. This means you can't do things like this:
Array.prototype.myShift = function() {
this = this.slice(1);
};
This is because Array.prototype.slice returns a new array and does not modify the old array. Other methods, however, such as Array.prototype.splice, do modify the old array. So you can do something like this:
Array.prototype.myShift = function() {
return this.splice(0, 1)[0];
};
This will have exactly the same behaviour as the standard Array.prototype.shift method. It modifies the current array, so you can do this:
var labelRow = this.myShift();