Would like to stop execution of code when a match is met - arrays

I created this service method in Angular JS which checks if an array of potential statuses(pendingApplications) match any of an array of set statuses(applicableStatuses). For this to work it meetsStatusCondition should return true after the first match occurs. Only 1 of the numbers in pendingApplications array needs to match and I'd like to end the execution of this function. Currently it's looping through every item in pendingApplications array
`containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.forEach(function(status) {
if (applicableStatuses.includes(status)) {
return pendingApplications.meetsStatusCondition = true;
}
});
}`

This is a limitation with .forEach, you can't break out if it like you can with a for loop
Just a regular for loop will work
for (const status of applicableStatuses){
if (applicableStatuses.includes(status)) {
pendingApplications.meetsStatusCondition = true;
break //or return if you want to exit out of the enclosing function instead of just the loop
}
}

Often when you want to short-circuit a forEach like this, what you're really looking for is another method like find() or some().
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.meetsStatusCondition = pendingApplications.some(function(status) {
return applicableStatuses.includes(status)
});
}

There is no point in using forEach (which doesn't have a breaking option) if you could just use a regular for ... of loop instead:
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
for (const status of pendingApplications) {
if (applicableStatuses.includes(status)) {
pendingApplications.meetsStatusCondition = true;
break;
}
}
}
However, even this seems a bit too complicated, you could just set meetsStatusCondition to the result of some:
containsApplicableStatus: function(pendingApplications, applicableStatuses) {
pendingApplications.meetsStatusCondition =
pendingApplications.some(status => applicableStatues.includes(status));
}
I do wonder if it makes sense to set a non-index property on your array though, maybe rethink that. This works but it's usually not something you'd expect on an array, and it will be lost if you convert that array to JSON for instance.

Related

Laravel Checking if Array or Collection is not Empty to run

I have an object of $person as below:
$person = Person::where('id', $id)->first();
According to which $person exists or not I load other data:
if($person) {
$person->family_members = FamilyMemberController::FamilyMemberOf($person->id);
} else {
$person->family_members = [];
}
In the view file, I check the $person->family_members if not empty and exists to add a generated value :
if(!empty(array_filter($person->family_members))) {
// my code
}
But it throws an error:
array_filter(): Argument #1 ($array) must be of type array, Illuminate\Database\Eloquent\Collection given
I need to check this $person->family_members to make sure whether it's an array or a collection is not empty.
Writing code for if array do something if collection do something is the wrong way of implementation.
You can do two things.
use both returns as collection()
or either use both returns as an array[]
If collection
else {
$person->family_members = collect();
}
If array
use ->toArray() at the end of Eloquent. Check this answer
As well, I think you are confused with array_filter(). Maybe you are searching for in_array() or contains()
Use count method
if(count($person->family_members)>0){
//your code
}
We don't know your code, but given the error, it's safe to assume your method returns a Collection. You can see available methods in the docs. However, if you need it as array, all you need to do is call ->toArray() on the result Collection. Then you can use array_filter.
What about just doing
if(!$person->family_members){
// your code here
}
or
if($person->family_members){
// your code here
} else {
// code of "if it's empty" goes here
}
You can use the count() function to return a count of an index. ex
if(count($person->family_members)){
//do your true algo
}
Why you are using the empty method ?! Try this:
$person->family_members = $person ? FamilyMemberController::FamilyMemberOf($person->id) : null;
if($person->family_members){ // your code }
Try simple ways in Programming ;)

How to get result out of for loop

I have a function in swift and I am using a for loop in it.
let pointTF = [emailTF,passTF,resetEmailTF]
for i in 0...pointTF.count
{
return coachMarksController.helper.makeCoachMark(for: pointTF[i])
}
I want to return this value outside the loop? How can I do that? Please help
Assuming the above code is wrapped in a function you can define an array of CoachMark objects outside the scope of the for loop, and append the generated coachMark to the array:
var coachMarks: [CoachMark]()
for i in 0...pointTF.count
{
var cm = coachMarksController.helper.makeCoachMark(for: pointTF[i])
coachMarks.append(cm)
}
//Then you can return a single CoachMark:
return coachMarks[1]
Don't really know what you are returning, but if you want to return an array of the results you loop through, i suggest using a map for it, neat and simple.
return pointTF.map({ coachMarksController.helper.makeCoachMark(for: $0) })

Access returned computed array within method and manipulate

I have a computed array which is full of tags and updates depending on what selection i make in the select box. I would like to take this array and pass it to a method and then run a method to update what “results” have an active class. Although I get an array saying I can’t run forEach on this element.
Been through a few topics and understand computed properties dont work like that but surely there is a way around this.
https://jsfiddle.net/39jb3fzw/6/
Short Snippet
methods: {
updateOutput() {
var tags = this.tagArray;
tags.forEach(function(tag) {
console.log(tag);
})
}
},
computed: {
concatenated: function () {
var ret = this.selected.concat(this.selected2, this.selected3);
this.tagArray = ret;
//this.updateOutput();
return ret;
}
}
Full Output
https://jsfiddle.net/39jb3fzw/6/
Thanks again :slight_smile:
It looks like the issue is the line:
var ret = this.selected.concat(this.selected2, this.selected3);
That line of code is returning an empty string rather than an array. This is because this.selectedX is a string rather than an Array. This explains why tag.forEach is undefined. forEach doesn't exist on the String prototype.
You can create this an array instead be doing
var ret = [ this.selected, this.selected2, this.selected3 ]
From there you can set this.tagArray to ret
Hope this helps

Angular promises run conditionally

I'd like to perform an asynch function conditionally, but I think I'm missing the correct syntax to say what I want.
this.doUpToThreeThings = function(skipTheMiddleStep) {
return doFirstThing().then(function (result) {
if (skipTheMiddleStep) {
return doThirdThing();
} else {
return doSecondThing();
}
}).then(function (result) {
if (skipTheMiddleStep) {
return "ok"; // return what?
} else {
return doThirdThing();
}
});
}
By the time we get to the second then, I don't know if the first block did the middle step, so I'm forced into repeating the condition. And the second block reads weird: it should say, if skip the middle step, then do the third thing, but since it we know that the previous block must have done the third thing, it just returns. So I have to repeat the condition and write pretty wrong-looking code in the second then.
I realize I can write a function called doSecondAndThirdThings, and just call that from the condition in the first block, but that's not really DRY, it's just hiding the non-DRYness. (or maybe I'm wrong about that?)
Also, I'm still a little confused about returning a completed promise on that "ok" branch. Is that right how it is, or should I say something like resolve? -- Thanks
The deferred in thefourtheye's answer is pointless and is considered an anti pattern with promises.
Here is how I would do it:
this.doUpToThreeThings = function(skipTheMiddleStep) {
return doFirstThing().then(function (result) {
return (skipTheMiddleStep) ? doThirdThing() : doSecondThing().then(doThirdThing);
});
}

How would I remove a "row" in an array depending on the value of an element?

Here's what I'm currently doing/trying to do to accomplish my goal. But it is not removing the "row" the way I would like it too.
So, I'm making an object, then pushing it into an array. And the adding to the array part works fine and just as I expect.
var nearProfileInfoObj:Object = new Object();
nearProfileInfoObj.type = "userInfo";
nearProfileInfoObj.dowhat = "add";
nearProfileInfoObj.userid = netConnection.nearID;
nearProfileInfoObj.username = username_input_txt.text;
nearProfileInfoObj.sex = sex_input_txt.selectedItem.toString();
nearProfileInfoObj.age = age_input_txt.selectedItem;
nearProfileInfoObj.location = location_input_txt.text;
nearProfileInfoObj.headline = headline_input_txt.text;
theArray.push(nearProfileInfoObj);
So after that later on I need to be able to remove that object from the array, and it's not working the way I'm expecting. I want to take a variable whoLeft and capture their ID and then look in the array for that particular ID in the userid part of the object and if its there DELETE that whole "row".
I know you can do a filter with an array collection but that doesnt actually delete it. I need to delete it because I may be adding the same value again later on.
whoLeft = theiruserIDVariable;
theArray.filter(userLeaving);
public function userLeaving(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
return false;
}
else
{
return true;
}
}
But this doesnt seem to be deleting the whole row like it implies. Does anyone know what i'm doing wrong?
Instead of modifying the original array, the new filtered array is returned by the filter method. So you need to assign the returned array to theArray.
Try this
theArray = theArray.filter(userLeaving);
EDIT This turned out to be slower than for loop:
An alternative to the hand coded loop could be something like this:
theArray.every(searchAndDestroy);
public function searchAndDestroy(element:*, index:int, arr:Array):Boolean
{
if (element.userid == whoLeft)
{
arr.splice(index,1);
return false;
}
return true;
}
As far as I know, every() terminates the first time the test function returns false. So the question is: for a big list, which is faster, the for loop or the loop that every() does with the overhead of the test function call.
EDIT #2 But this was faster than a for loop for a test I ran on an array of a million Points:
for each(var element:Object in theArray)
{
if (element.userid==whoLeft)
{
theArray.splice(theArray.indexOf(element),1);
break;
}
}
I think this is what you're looking for:
for(var i:uint = 0, len:uint = theArray.length; i<len; i++)
{
if(thisArray[i].id == whoLeft.id)
{
thisArray.splice(i, 1);
break;
}
}
However, do you really need it in an Array because you could always use a Dictionary which would mean accessing it by id which would be a lot simpler to remove.

Resources