Consider BigQuery Schema "Time=Timestamp, Data=String" and the following two rows
2012-11-01 03:45:23 UTC, { "Sensor1": [45.56], "Sensor2": [45.56], "Sensor3": [34.45]}
2012-11-01 05:45:23 UTC, { "Sensor1": [11.43], "Sensor2": [NaN], "Sensor3": [12.34]}
Then SELECT Time, JSON_EXTRACT(Data, '$.Sensor1') is perfect
2012-11-01 03:45:23 UTC, [45.56]
2012-11-01 05:45:23 UTC, [11.43]
but SELECT Time, JSON_EXTRACT(Data, '$.Sensor3') gives
2012-11-01 03:45:23 UTC, [34.45]
2012-11-01 05:45:23 UTC, null
Is that expected behaviour? Would I be better off just omitting that NaN from Sensor 2?
This is an expected behavior. As per https://www.json.org/json-en.html, valid JSON values can only be string, number, true or false or null. Hence NaN is interpreted by BigQuery as null since it is considered as an invalid value.
A value can be a string in double quotes, or a number, or true or
false or null, or an object or an array. These structures can be
nested.
If you want retain the value NaN you can enclose it with double quotes ("NaN") but it will be considered as string. Or you can just omit the NaN as you mentioned in your question if you won't be using/needing it.
So for my application I always have { "nameA": [array...], "nameB": [array...], ...}
where array is the usual range of floating point numbers, i.e. including some NaN's. As noted above, JSON_EXTRACT doesnt really work. But this javascript UDF does the job just fine.
CREATE TEMP FUNCTION EXTRACT_DATA(mystr STRING, param STRING)
RETURNS Array < FLOAT64 > LANGUAGE js AS
"""
const i0 = mystr.indexOf(param);
if (i0 == 0) {
return null;
}
const i1 = mystr.substring(i0).indexOf("[");
if (i1 == 0) {
return null;
}
const i2 = mystr.substring(i0+i1).indexOf("]");
if (i2 == 0) {
return null;
}
const myArray = mystr.substr(i0+i1+1,i2-1).split(',')
return myArray.map(Number);
}
""" ;
I don't know how expensive ($'s and cpu_time) would this be compared to JSON_EXTRACT on arrays that didn't have NaN.
Related
On the Android Studio emulator The user is required to enter a maximum of 10 numbers. When I put in the number 1 the output shows 0 instead of 1 (this is for the min number; the max works perfectly fine) Can anyone please assist me in this problem. I tried using minOf() and max() nothing worked Below is a snippet of my source code:
val arrX = Array(10) { 0 }
.
.
.
.
findMinAndMaxButton.setOnClickListener {
fun getMin(arrX: Array<Int>): Int {
var min = Int.MAX_VALUE
for (i in arrX) {
min = min.coerceAtMost(i)
}
return min
}
fun getMax(arrX: Array<Int>): Int {
var max = Int.MIN_VALUE
for (i in arrX) {
max = max.coerceAtLeast(i)
}
return max
}
output.text = "The Min is "+ getMin(arrX) + " and the Max is " + getMax(arrX)
}
}
}
Is there anything that can be done to get this work?
You're initialising arrX to a bunch of zeroes, and 0.coerceAtMost(someLargerNumber) will always stick at 0.
Without seeing how you set the user's numbers it's hard to say what you need to do - but since you said the user enters a maximum of 10 numbers, at a guess there are some gaps in your array, i.e. indices that are still set to 0. If so, they're going to be counted in your min calculation.
You should probably use null as your default value instead - that way you can just ignore those in your calculations:
val items = arrayOfNulls<Int?>(10)
// this results in null, because there are no values - handle that however you like
println(items.filterNotNull().minOrNull())
>> null
// set values on some of the indices
(3..5).forEach { items[it] = it }
// now this prints 3, because that's the smallest of the numbers that -do- exist
println(items.filterNotNull().minOrNull())
>> 3
Ex 10.0 = 10
10.3 = 10.3
10.7 = 10. 7
Looking for a convenient way from Kotlin Standard library
You can use the following function:
fun removeTrailingZeros(num: String): String {
if(!num.contains('.')) // Return the original number if it doesn't contain decimal
return num
return num
.dropLastWhile { it == '0' } // Remove trailing zero
.dropLastWhile { it == '.' } // Remove decimal in case it's the last character in the resultant string
}
You can verify the code here
You can try this:
double number = 23.471;
if (number % 1 != 0)
{
//round off here
System.out.print ("Decimal");
}
else
{
System.out.print ("Integer");
}
If you want to get a string, the easiest way is to work with a string like num.toString().replace(".0",""). For numbers conversion does not make sense since the resulting type is different for different inputs.
I want to format the number to String and fill 0 when it's not enough two characters
fun formatDuration(val duration):String {
val minutes = duration.toInt() / 60
return "$minutes"
}
For example, if minutes is 6, it should displayed 06 rather than 6.
You can padStart the toString() result of minutes.
I tried your code in the Kotlin Playground and it wasn't compilable / runnable. For the following example, I had to change parts of your fun:
fun main() {
println(formatDuration(364.34))
}
fun formatDuration(duration: Double): String {
val minutes = duration.toInt() / 60
// fill the result to be of 2 characters, use 0 as padding char
return minutes.toString().padStart(2, '0')
}
Executing this results in the output 06.
Alternatively, you can simply use String.format() from Java, just
return "%02d".format(minutes)
instead of return minutes.toString().padStart(2, '0'), the result stays the same.
You can achive this with padStart
Example:
val padWithSpace = "125".padStart(5)
println("'$padWithSpace'") // ' 125'
val padWithChar = "a".padStart(5, '.')
println("'$padWithChar'") // '....a'
// string is returned as is, when its length is greater than the specified
val noPadding = "abcde".padStart(3)
println("'$noPadding'") // 'abcde'
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
val secNum:Unit = listNumber1to100.forEach {it}
println(listNumber1to100.asSequence().filter { it%(listNumber1to100.forEach { it })!=0 }.toList())
I have an error in reminder sign!
This is Error: None of the following functions can be called with the arguments supplied
In your first approach, the error appears in this line:
it%(listNumber1to100.forEach { it })
A Byte, Double, Float, Int, Long or Short is prefered right after the % operator, however, forEach is a function which the return type is Unit.
In your second approach, you have the correct expression in isPrime(Int). Here are some suggestions for you:
listNumber1to100 is excluding 100 in your code, if you want to include 100 in listNumber1to100, the lambda you pass to takeWhile should be changed like this:
val listNumber1to100 = listNumbers.takeWhile { it <= 100 }
listNumber1to100.asSequence() is redundant here since listNumber1too100 is itself a TakeWhileSequence which implements Sequence.
isPrime(Int) is a bit confusing since it is check for isComposite and it does not work for every input it takes(it works for 1 to 99 only). I will rewrite it in this way:
fun isPrime(num: Int): Boolean = if (num <= 1) false else !(2..num/2).any { num % it == 0 }
Since prime number must be positive and 1 is a special case(neither a prime nor composite number), it just return false if the input is smaller or equal to 1. If not, it checks if the input is divisible by a range of number from 2 to (input/2). The range ends before (input/2) is because if it is true for num % (num/2) == 0, it is also true for num % 2 == 0, vise versa. Finally, I add a ! operator before that because a prime number should not be divisible by any of those numbers.
Finally, you can filter a list by isPrime(Int) like this:
println(listNumber1to100.filter(::isPrime).toList())
PS. It is just for reference and there must be a better implementation than this.
To answer your question about it, it represents the only lambda parameter inside a lambda expression. It is always used for function literal which has only one parameter.
The error is because the expression: listNumber1to100.forEach { it } - is not a number, it is a Unit (ref).
The compiler try to match the modulo operator to the given function signatures, e.g.: mod(Byte) / mod(Int) / mod(Long) - etc.
val listNumbers = generateSequence(1) { it + 1 }
val listNumber1to100 = listNumbers.takeWhile { it < 100 }
fun isPrime(num: Int): Boolean = listNumber1to100.asSequence().any { num%it==0 && it!=num && it!=1 }
println(listNumber1to100.asSequence().filter { !isPrime(it)}.toList())
I found this solution and worked
But why can I have a non-number here in the right side of reminder
I'm trying to figure out how to use sprintf to print at least two decimal places and no leading zeros. For instance
input:
23
23.0
23.5
23.55
23.555
23.0000
output:
23.00
23.00
23.50
23.55
23.555
23.00
any formatting help would be appreciated
There is no such built-in format specifier. You could check if the number to be printed has two or fewer decimals (round to two decimals and compare), and if so use %.02f. If the number has more decimals, use a %g specifier. Here's an example in Ruby:
def print_two_dec(number)
rounded = (number*100).to_i / 100.0
if number == rounded
printf "%.02f\n", number
else
printf "%g\n", number
end
end
[ 23, 23.0, 23.5, 23.55, 23.555 ].each do |number|
print_two_dec(number)
end
Outputs:
23.00
23.00
23.50
23.55
23.555
in PHP you could use
<?php
$number = 0.56;
echo sprintf("%0.2f",$number);
In PHP, you may use the number_format function for this purpose, too, which also allows you to change delimiters.
In php this is what I did (inspired by this post). Maybe not the most elegant but... I made a function for printing numbers as strings. I wanted to be able to have flexibility so I have a couple of parameters.
PHP:
function print_num($num,$numdec,$atleast = false,$max_dec = -1)
{
$ret_norm = false;
if (!$atleast)
$ret_norm = true;
else //atleast = true
{
//Want at least $numdec decimals
//Do we have two or fewer and want to return two or fewer?
if ($num == ((int)($num*100)/100) & $numdec <= 2 )
$ret_norm = true;
else
{
//See if we have enough dec. already
$just_dec = substr((string)$num,strpos((string)$num,".") + 1);
if ($numdec >= strlen($just_dec))
$ret_norm = true;
else
{
//More decimals than at least value - make sure we don't go over max if set
if ( $max_dec >= 0 && strlen($just_dec) > $max_dec )
{
//Confine to max_dec length
$ret_norm = true;
$numdec = $max_dec; //Set for sprintf below
$num = number_format($num,$max_dec); //Round the value so doesn't just chop off
}
else if ($max_dec >= 0)
$ret_norm = false;
} //else
} //else
} //else atlest
if ($ret_norm)
return sprintf("%0.".$numdec."f",$num);
else
return sprintf("%s",$num); //print as is
} //print_num
And to call the function (to have at least two decimals but max 4:
print_num($mynum,2,true,4);
If the number is 34.1, you get 34.10
If the number is 34.12345 you get 34.1235
etc.
Does "23.555".toFixed(2) not do what I think it does? (Javascript)