I am programming in Fortran and if all single elements of my array are positive I want to execute statement 1, if they are partly positive execute statement 2 and if all are negative execute statement 3.
I know I will probably need a 'do' loop and a 'if' construct but could not figure out how to do it best.
There is no need to use loop for a simple condition
if (ALL(A>0)) then
statement1
else if (ALL(A<0)) then
statement3
else
statement2
end if
Explanation: A>0 is an array of logical values based on evaluating the condition for each element of the original array A. Function ALL() then reduces this logical array and returns true if all elements are true and false otherwise.
You request a do loop in the title. If you really need to fix a particular error with that, you must show us the code from your efforts, your errors and all other important details.
Related
I have found one case that does not make sense.
I have following feature:
test_array_deep_copy: BOOLEAN
local
imp, old_imp: ARRAY[STRING]
do
comment("Test of a deep copy.")
create {ARRAY[STRING]} imp.make_empty
imp.force ("Alan", 1)
imp.force ("Mark", 2)
imp.force ("Tom", 3)
old_imp := imp.deep_twin
imp[2] := "Jim"
Result :=
across
1 |..| imp.count as j
all
j.item /= 2 implies imp [j.item] = old_imp [j.item]
end
check not Result end
end
Since it is deep copy, that means address of imp and old_imp are different, as well as that its attributes in both two also refers to different address.
So, this "Result" after across loop, it should be false because addresses in imp and old_imp at same index are different.
So when I debug this code, it say Result is set to be false after finishing across loop.
The problem is that "check not Result" does not make false to true.
If I run workbench system, it says following:
I do not know why. "not" before "Result" in "check not Result" statement should make its whole check true, so it should say "PASSED" in workbench system, but it fails.
why is that?
Your reasoning is correct and the test query as written should return False. Most probably, the system reports FAILED as soon as the query returns False. So, what needs to be done is to fix the query itself.
The items of the array are cloned and therefore the equality = used in the loop gives False for all elements. To get True from the loop, a different equality operator has to be used: ~. It compares objects rather than references. After that change the query gives True and the test should pass.
An alternative would be to replace the equality operator with a call to the feature is_deep_equal:
imp [j.item].is_deep_equal (old_imp [j.item])
Unlike the operator ~ that uses the user-defined feature is_equal to compare objects – strings in the example – is_deep_equal performs "deep" equality test by traversing the whole object tree. The test should pass in this case as well. But deep equality is rarely used in practice.
I think this should be a straightforward question, but for some reason I can't find a solution anywhere.
I have a lengthy formula in excel that, ultimately, returns an array of four items -- i.e. {1,2,0,0}. I want to count how many of the resulting numbers are greater than zero.
When I use =COUNT({1,2,0,0}) on this result, I get the expected answer of 4. But when I try to use =COUNTIF({1,2,0,0}, ">0") it pops up with an error saying that my formula has a problem.
Is there something I'm doing wrong? Is there an array equivalent for COUNTIF() ?
It appears the COUNTIF function only works on ranges, while the COUNT function can utilize an array.
Give SUMPRODUCT a try. Below is a slightly expanded form of your example which I used to test the formula. It basically checks to see if each value in the array is greater than 0, and if it is, it assigns it a value of 1. Then SUMPRODUCT goes through and adds up all the 1s to give you the total number of values greater than 0.
=SUMPRODUCT(IF({1,0,3,0,5,0,0,6,9,9,0,7,0}>0,1,0))
Probably the most concise way to accomplish this is to just convert the TRUE or FALSE value returned from the validation check into a number with the INT function. TRUE translates to 1 and FALSE translates to 0. Then SUM those 1's and 0's.
=SUM(INT({1,2,0,0}>0))
Or as Barry Houdini points out, you can coerce the boolean to an int with:
=SUM(({1,2,0,0}>0)*1)
Or:
=SUM(({1,2,0,0}>0)+0)
Just stumbled across a bug in some old code of mine where to check if an array was empty or not I just wrote:
if my_array
...(do stuff)
end
instead of using isempty or something like that.
What I have discovered is that "if my_array" returns 0 only if the array is indeed empty OR if one or more of the components in the array are 0.
Is this expected? What exactly is going on? Is matlab performing an and operation on all the elements?
Many thanks
That is exactly the behaviour as it is documented:
An evaluated expression is true when the result is nonempty
and contains all nonzero elements (logical or real numeric). Otherwise,
the expression is false.
I'm developing some stored proceduces in PL/pgSQL and some of them are giving me some problems. The sprocs I'm developing receive by parameter an array which I use in a FOR LOOP to get all its elements. To define the upper bound of the FOR LOOP I use the array_length function.
FOR i IN 1..array_length(array,1) LOOP
--array[i] something in here
END LOOP;
The problems occurs when I give to the sprocs an empty array. Instead of not entering the cycle, the sproc simply returns an error, stating that the upper bound of the FOR LOOP is NULL. Shouldn’t it be 0?
Am I doing anything wrong with the FOR LOOP?
Is there any other way to use the same bounds in a LOOP without it returning NULL when using an empty array?
Note: I know I can always use a condition before the LOOP, like this:
IF array_length(array,1) IS NOT NULL THEN
but the problem is: This sproc is supposed to process thousands of calls in the shortest amount of time. As so, I'm not looking to something that adds an unnecessary overhead to the processing. I'm just looking if there is any way to “cycle” an empty array in a LOOP.
As always, if you want to have different behavior for NULL values, use the coalesce construct:
FOR i IN 1..coalesce(array_length(array, 1), 0) LOOP
RAISE NOTICE '%', array[i];
END LOOP;
As for the return value: array_length(x, N) returns the number of elements in Nth dimension. Since an empty array has no dimensions, it returns NULL. You're right that it's counterintuitive if you only consider simple arrays, but makes sense for multi-dimensional arrays.
Edit: Like Erwin Brandstetter wrote in the comments, it's more correct to use array_lower/upper to loop over array indices. These will work for arrays that are not 1-based. These also take a dimension argument and require coalesce:
FOR i IN coalesce(array_lower(array, 1), 1)..coalesce(array_upper(array, 1), 1) LOOP
RAISE NOTICE '%', array[i];
END LOOP;
Avoid the problem altogether by looping through the array with FOREACH, introduced with Postgres 9.1:
FOREACH i IN ARRAY $1
LOOP
-- do something
END LOOP;
Depending on what you want to do inside the loop, you might be able to avoid looping altogether and use plain SQL with unnest() instead. Set-based operations are typically faster than looping in PostgreSQL.
Example:
RETURN QUERY
SELECT elem || 'foo'
FROM unnest($1) AS t(elem);
I'm working with some legacy spaghetti code that processes some hairy EDI. Most of the code is indecipherable and has no indentation or comments or even good variable names but there's one line that gives me trouble when I remove the On Error Resume Next statement which causes the script to always timeout.
If UBound(arylin) >= 1 Then
Do Until arylin(0) = "PB" and arylin(1) = "DEF"
' Processing goes here - not relevant for this
Loop
End If
The script executes the conditional but errors at the "Do Until" line, saying:
Microsoft VBScript runtime error '800a0009'
Subscript out of range: '[number: 0]'
Now, why on Earth would this be giving an error if I'm testing the upper bound before checking it, and it's saying that the upper bound is at least 1?
I can post more of the code if I have to but I'd rather not since my predecessor was a complete hack and the code is extremely ugly.
See AnthonyWJones comment)(With VB you can set the base of arrays to start at either 0 or 1 - it should be at or near the top of a module: look for Option Base 1 or Option Base 0.)
LBound will always return 0.(You can also use LBound() to check the lower boundary of the array.)
(Just goes to show: don't expect MS to be consistent!)
Although you check that the array-size is >= 1 - which will ensure that arylin(0) is valid, but not necessarily arylin(1). The index is zero-based so if one element exists, it will be at index=0, and index=1 will be out-of-bounds.
You must check that the array-size >= 2 in this case. If you use two entries following each other consistently, then the check must be made for (array-size) mod 2 = 0.
Also make sure what value UBound actually returns. I googled and got contradicting information: this says it returns the 'count' while this one says it returns the physical limit (= 'count' -1).
About the 'On Error Resume Next' thing, maybe it should stay there ...
UBound() returns the index of the last element in the array. By default, arrays in vb languages prior to vb.net start at 1 rather than 0 (meaning the count and the index are normally the same thing, though you can change the default with Option Base).
Put those together you'll see that it's failing here:
arylin(0) = "PB"