In this conditional JSX rendering, why is a double (!!) required? - reactjs

In the following JSX
Why is there a double !
{!! count && <div className={'styles.info'}>{`did this ${count}`}</div>}

You don't want the space between !! and count. They should be together like so: !!count.
Like the comment said, it is coercing the value to a boolean. If count is a falsey value, say 0, it would still be rendered by React. Using !! to coerce 0 to false, would guarantee that 0 is never rendered.

Related

trying to get the value of the struct inside an array

Looking for a one liner code either in java or cfm, where i do not need to loop over te array of structs to use te structfind to get the value from it.
right now looking at it,
Coldfusion - How to loop through an Array of Structure and print out dynamically all KEY values?
where i can loop over and get the value of the key match
but trying to check if something like this can be done
<cfset myvalue = structfindvaluefromAnything(myarrayofstruct,"infor")>
I like Sev's approach. I would change it slightly
<cfscript>
superheroes=[
{"name":"Iron Man","member":"Avengers"},
{"name":"Spider-Man","member":"Avengers"},
{"name":"Wonder Woman","member":"Justice League"},
{"name":"Hulk","member":"Avengers"},
{"name":"Thor","member":"Avengers"},
{"name":"Aquaman","member":"Justice League"}
];
avengers = superheroes.filter(function(item) {
return item.member == "Avengers";
});
writeDump(avengers);
</cfscript>
If you really want to do it in one line then you could use ArrayFilter() in combination with StructFindValue().
Adapting from the Adobe docs for ArrayFilter - https://helpx.adobe.com/coldfusion/cfml-reference/coldfusion-functions/functions-a-b/arrayfilter.html - something like this:
<cfscript>
superheroes=[
{"name":"Iron Man","member":"Avengers"},
{"name":"Wonder Woman","member":"Justice League"},
{"name":"Hulk","member":"Avengers"},
{"name":"Thor","member":"Avengers"},
{"name":"Aquaman","member":"Justice League"}
];
avengers=ArrayFilter(superheroes,function(item){
return ArrayLen(StructFindValue( item, "Avengers"));
});
writeDump(var=avengers, label="all matches");
writeDump(var=ArrayLen(avengers) ? avengers[1] : "Not found", label="first match only");
writeDump(var=structFindValue({"a":superheroes}, "Avengers", "all"), label="without arrayFilter");
</cfscript>
I believe the function available for this nearly exactly what you were hoping for...
StructFindValue(struct, value [, scope])
Searches recursively through a substructure of nested arrays, structures, and other elements for structures with values that match the search key in the value parameter.
Returns an array that contains structures keys whose values match the search key value. If none are found, returns an array of size 0.
Based on the gist you provided above (https://cffiddle.org/app/file?filepath=3e26c1ac-d5db-482f-9bb2-995e6cabe704/49b3e106-8db9-4411-a6d4-10deb3f8cb0e/24e44eba-45ef-4744-a6e6-53395c09a344.cfm), I think you've clarified your expectations a little bit.
In your gist, you say you want to be able to search an array of structs and find the row that has a "name" key with a value of "form". Then, you want to take the value of the "value" key that's associated with that struct in the array row. If there is no value then return 0.
You wanted to be able to do this in a single line of code, and the above answers do accomplish that. My answer essentially builds on those.
As demonstrated in the earlier answers, you still want to use closure functions to filter down your final output. Those are very quick and essentially built to do what you're trying to do.
The Fiddle that I worked with is here: https://cffiddle.org/app/file?filepath=b3507f1d-6ac2-4900-baed-fb3faf5a3b3a/e526afc2-bb85-4aea-ad0e-dcf38f52b642/75d88d2b-f990-44c1-9d9f-22931bf9d4d7.cfm
I've done two things with this.
First, I worked it as if you expected to encounter multiple records for your filtering value, and then turn those into a comma-delimited list. If you need another structure, the reduce() function in my code can be modified to handle this.
Second, I worked it as if you expected to encounter only one filtered record, returning only a single value.
The first thing I did, which is mostly the same in both methods, and which is essentially the same as the previous answers, is to filter your original array for just the value you want.
This is done like this:
myResult = originalArray.filter(
function(itm){
return itm?.name=="form"; /// ?. = safe-navigation operator.
}
)
I've broken it to multiple lines for clarity.
This will return a new array of structs consisting of your filtered rows.
But then you want to take those records and return the "value" from those rows (defaulting to 0 if no value. You can do this with a reduce().
commaDelimitedValue =
myResult.reduce(
function(prev,nxt) {
return prev.listappend( ( nxt.value.len() ? nxt.value : 0 ) ) ;
}
, "" /// Initialization value
) ;
Again, this can be written in one row, but I've included line breaks for clarity.
The reduce() function essentially just reduces your input to a single value. It follows the format of .reduce( function( previousValue, nextValue ){ return .... },<initializationValue>), where, on the first iterations, the initializationValue is substituted for previousValue, then previousValue becomes the result of that iteration. nextValue is actually the current iteration that you will derive a result from.
More at: https://coldfusion.adobe.com/2017/10/map-reduce-and-filter-functions-in-coldfusion/
In my assumption here, you could possibly have multiple rows returned from your filter(). You take those rows and append the value to a commma-delimited list. So you would end up with a result like 20,10,0,0 - representing 4 rows in your filtered results.
I also check for a length of the value and default it to 0 if it's an empty string. Above, I said that you could just use an Elvis Operator (:?) on that, but that doesn't work for a simple value like an empty string. Elvis works with NULLs, which the earlier array did have.
To put this back to one line, you can chain both of these functions. So you end up with:
myFinalResult =
myOriginalArray.filter(
function(itm){
return itm?.name=="form";
}
)
.reduce(
function(prev,nxt) {
return prev.listappend( ( nxt.value.trim().len() ? nxt.value : 0 ) ) ;
}
, ""
)
;
Again, that code is doing a lot, but it is still essentially one line. The final result from that would again be something like "20,10,0,0" for 4 rows with 2 defaulted to 0.
If you only expect your filter to return a single row, or if you only want a single value, you can simplify that a little bit.
myFinalResult = myOriginalArray.filter( function(itm){ return itm?.name=="fm" && (itm?.value.trim().len()>0) ; } )[1]["value"] ?: 0 ;
With this, I am back to using my previous trick with Elvis to default a row with no value, since I am filtering out the "form" struct with an empty-string "value". && is the same as AND. Technically this CAN filter more than one row from the original array, but the [1] will only pick the first row from the filtered rows. It also doesn't need to use a reduce(). If there's more than one row filtered, each iteration will just overwrite the previous one.
This will return a simple, single value with something like 42 - which is the last filtered value in the array, since it overwrites the previous row's value.
My Fiddle (https://cffiddle.org/app/file?filepath=b3507f1d-6ac2-4900-baed-fb3faf5a3b3a/e526afc2-bb85-4aea-ad0e-dcf38f52b642/75d88d2b-f990-44c1-9d9f-22931bf9d4d7.cfm) has some additional comments, and I set up a couple of edge cases that demonstrate the filtering and safe-navigation.
I would also like to reiterate that if this is Lucee 5+ or ACF2018+, you can shorten this further with Arrow Functions.

Can any one explain why we need if (prime[2]!=1) to assign the values to the array while all the values of the array are initially set to be zero?

enter image description here
I have this code as an assignment where I should store values for each number from 0 to 100. Prime numbers are assigned the value 1 while non-prime are assigned the value 0. The code without the If statement and simply a return statement at the end makes more sense especially that the If condition is always true since all values of the array are initiated with zero, however, without the If, the code doesn't function properly. It usually returns 0 for all numbers. So the If condition here is crucial but can anybody explain why and what does it do here to make the code work?

Solution to Error: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()

I have a function where I'm calculating two float values with a conditional if statement for the return values shown below:
# The function inputs are 2 lists of floats
def math(list1,list2):
value1=math(...)
value2=more_math(...)
z=value2-value1
if np.any(z>0):
return value1
elif z<0:
return value2
Initially, I ran into the title error. I have tried using np.any() and np.all() as suggested by the error and questions here with no luck. I am looking for a method to explicitly analyze each element of the boolean array (e.g. [True,False] for list w/ 2 elements) generated from the if statement if z>0, if it is even possible. If I use np.any(), it is consistently returning value1 when that is not the case for the input lists. My problem is similar to The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()? but it went unanswered.
Here's a simple example:
a = np.array([1,2,3,4]) #for simplicity
b = np.array([0,0,5,5])
c = b.copy()
condition = a>b #returns an array with True and False, same shape as a
c[condition] = a[condition] #copy the values of a into c
Numpy arrays can be indexed by True and False, which also allows to overwirte the values saved in these indeces.
Note: b.copy() is important, because other wise your entries in bwill change as well. (best is you try it once without the copy() and then have a look at what happens at b
If z is an array
z=value2-value1
if np.any(z>0):
return value1
elif z<0:
return value2
z>0 and z<0 will be boolean arrays. np.any(z>0) reduces that array to one True/False value, which works in the if statement. But the z<0 is still multivalued, and with give elif a headache.

How to assign an expression to a model?

I am having the following set up inside an ng-repeat directive:
<span ng-model="d.attr3">
{{d.attr2 - d.attr1}}
</span>
d is the variable used inside ng-repeat.
My issue is that I expect d.attr3 to hold the value of the expression inside span tag. However, it holds the expression NaN.
Note that I have converted the d.attr1 and d.attr2 values to integers - In fact, the expression evaluates correctly but it is not bound to the scope - how do I get d.attr3 to hold the value of the expression?
<span ng-init="d.attr3 = d.attr2 - d.attr1">
{{d.attr3}}
</span>

Array formula in excel suddenly not working... troubleshooting

I am currently using this array formula..
{=LARGE(IF(('Data Input'!$L$3:$L$15000=$B10)*('Data Input'!$H$3:$H$15000>$C10),'Data Input'!$O$3:$O$15000,0),1)}
Where B10 is a text ID, like 658A and L:L is the column with the IDs.
C10 is a date, with H:H being the column with dates.
O:O being the column with the # value that I am retrieving.
This formula works fine with my purposes when used with ctrl,shift,enter
The problem arises when I try to use...
{=IF('Data Input'!$L$3:$L$15000=$B10,1,0)}
It always returns a FALSE result, even though it works correctly in the first formula.
What is different about the second formula that changes the results?
This is very strange to me.
Thanks for any help.
the IF is only comaring the first value of the array that is returned, so only if the first comparison is true, will it return a true value.
Example to illustrate:
formula
Formula:
{=IF(A1:A3=B2,1,0)} will; return 0, unless cell A1 is changed to true. To change the result to have it return true if any of the values are true, you have to resort to a little trickery...
First, use -- to change the True/False values to 1/0, then use SUM to add them together. as IF treats any non-zero result as true, this will result in 1 being returned when any comparison is true.
Working through our example with the new formula {=IF(SUM(--(A1:A3=B2)),1,0)} (still an array formula) we get the following steps in evaluation:
=IF(SUM(--(A1:A3=B2)),1,0)
=IF(SUM(--(A1:A3=2)),1,0)
=IF(SUM(--({1,2,2}=2)),1,0)
=IF(SUM(--({False,True,True})),1,0)
=IF(SUM(0,1,1),1,0)
=IF(2,1,0)
=1
Your second formula is, itself, returning an array. You are only viewing the top left element in that return array - which happens to be FALSE.
Your first formula returns a scalar value; that is the difference.
If you want to sum the '1' values then your second formula could be amended to
{=SUM(IF('Data Input'!$L$3:$L$15000=$B10,1,0))}
which is also a scalar return.

Resources