Cratedb loop over column Array and see if the values fall between X and Y - cratedb

Hey stack overflow so I have a column called itemPrices that is an Array of integers;
[43, 44, 55]
So I have an api that gives me two numbers, X and Y. I want to take those two numbers and compare it against the Array. If the number in the object falls within X and Y I would like to retrieve the contents. How would i do such a thing in crateDB?

This can also be solved by using the array_min(array) and array_max(array) scalar functions:
cr> CREATE TABLE t1 (arr ARRAY(INTEGER));
CREATE OK, 1 row affected (1.918 sec)
cr> INSERT INTO t1 (arr) VALUES ([43, 44, 45]), ([42, 22, 105]);
INSERT OK, 2 rows affected (0.112 sec)
cr> SELECT arr FROM t1 WHERE array_min(arr) >= 43 AND array_max(arr) <= 45;
+--------------+
| arr |
+--------------+
| [43, 44, 45] |
+--------------+
SELECT 1 row in set (0.008 sec)

CREATE OR REPLACE FUNCTION filter_item_price(ARRAY(REAL), INTEGER, INTEGER) RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS 'function filter_item_price(array_integer, min_value, max_value) {
if(array_integer === null || array_integer === undefined) {
return false;
}
return array_integer.some(element => element >= min_value && element <= max_value);
}';
SELECT "itemPrices"
FROM scp_service_transaction.transactions_v2
WHERE "tenantId" = 'aptos-denim'
AND "retailLocationId" IN (161)
AND array_find("itemPrices", 98, 100) limit 100;

This can be solved with a User-Defined Function.
If you want to find the elements in the array, you could use a function like this:
CREATE OR REPLACE FUNCTION array_filter(ARRAY(INTEGER), INTEGER, INTEGER) RETURNS ARRAY(INTEGER)
LANGUAGE JAVASCRIPT
AS 'function array_filter(array_integer, min_value, max_value) {
return Array.prototype.filter.call(array_integer, element => element >= min_value && element <= max_value);
}';
SELECT array_filter([5, 7, 20], 2, 8)
-- returns [5, 7]
If you only want to identify if there is a value within the given boundaries, you can also do this:
CREATE OR REPLACE FUNCTION array_find(ARRAY(INTEGER), INTEGER, INTEGER) RETURNS BOOLEAN
LANGUAGE JAVASCRIPT
AS 'function array_find(array_integer, min_value, max_value) {
return Array.prototype.find.call(array_integer, element => element >= min_value && element <= max_value) !== undefined;
}';
SELECT array_find([5, 7, 20], 5, 300);
-- returns true
SELECT array_find([5, 7, 20], 25, 300);
-- returns false

Related

find the first element in a list beyond some index and satisfying some condition

I have as Input:
A givenIndex
A list
I want to find the index of the first positive element in that list but ignoring all the indices that are strictly smaller than givenIndex
For example if givenIndex=2 and the list is listOf(1, 0, 0, 0, 6, 8, 2), the expected output is 4 (where the value is 6).
The following code gives the first positive element but It doesn't take into account ignoring all the indices that are smaller than givenIndex.
val numbers = listOf(1, 0, 0, 0, 6, 8, 2)
val output = numbers.indexOfFirst { it > 0 } //output is 0 but expected is 4
val givenIndex = 2
val output = numbers.withIndex().indexOfFirst { (index, value) -> index >= givenIndex && value > 0 }

How dose it work? (about map function in Kotlin)

I can't understand below logic.
I think when put 'a' into () in result, the value of result is 32.
Because of (0 until 1-1 -> 0), lastDays[it] is 31.
So result is 31 + 1 = 32.
But the value is 1.
I am studying Kotlin now.
val a = 1
var b = 1
val lastDays = listOf(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
val result = (0 until a - 1).map {
lastDays[it]
}.sum() + b
Please borrow me your wisdom.
0 until a - 1 results in 0 until 0, so it is an empty range. Mapping the empty range results in an empty list. Calling sum() on an empty list returns 0. Then you add 0 + b where b is 1.

Kotlin aggregate consecutive list elements

I'd like to sum up consecutive numbers in a Kotlin list.
If the list has a 0 then it should start summing up the numbers after 0. The result would be a list of sums. Basically sum up until the first 0 then until the next 0 and so forth.
For example:
val arr = arrayOf(1, 2, 0, 2, 1, 3, 0, 4)
// list of sums = [3, 6, 4]
At the moment I got it working with fold:
val sums: List<Int> = arr.fold(listOf(0)) { sums: List<Int>, n: Int ->
if (n == 0)
sums + n
else
sums.dropLast(1) + (sums.last() + n)
}
but I wonder if there is a simpler or more efficient way of doing this.
I would personally have written it this way:
val sums = mutableListOf(0).also { acc ->
arr.forEach { if (it == 0) acc.add(0) else acc[acc.lastIndex] += it }
}
Using a mutable list, you avoid having to do any drop / concatenation. The code is also easier to follow.
You can still convert it to an immutable list using .toList() if you need to.

Find the first element in a list that verify a condition

Assuming we are given a list of integers R = [3,5,3,6,0,6,7], an threshold x (integer) and a window size (integer) p. For example, x=4 and p = 2.
I need to find the first index t that verifies the the following conditions:
R[t] >= 4, R[t+1] >= 4. Since p=2, we need to only verify for two boxes t and t+1. If p was equal to 3 we will need to verify for t, t+1 and t+2.
Here the t I am looking for is 5 (indexing is starting from 0).
How to write this in a elegant way in Kotlin (rather than looping on the elements).
A tentative that is giving an error (x=4 and p = 2. The output should be 3 since we start indexing by 0):
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val firstIndex = numbers.find { it >= 4 for it in it..it+2-1}
val numbers = listOf(1, 2, 3, 4, 6, 8, 2)
val p = 2
val x = 4
val t = numbers.windowed(p).indexOfFirst { window -> window.all { it >= x } } // t == 3
t will be equal to -1 in case if no matches will be found
Use windowed to check groups of values for each index in the list. Use withIndex() so you are iterating with the indices, which you need in your final result. Then use firstOrNull() (which find() is a redundant alias of). And finally, take ?.index to get the index of the first entry that satisfies the condition, or null if none satisfy.
val x = 4
val p = 3
val list = listOf(2,5,3,6,0,6,7)
val t = list
.windowed(p)
.withIndex()
.firstOrNull { (_, sublist) -> sublist.all { it >= x } }
?.index
find Returns the first element matching the given predicate, or null if no such element was found.
If I've understood correctly, this should work:
fun main() {
val list = listOf(3,5,3,6,0,6,7)
val p = 2
val x = 4
val t = list.withIndex().windowed(p).firstOrNull() { window ->
window.all { it.value >= x }
}?.first()?.index
println(t)
}
Output:
5

How to use while loop inside a function?

I decide to modify the following while loop and use it inside a function so that the loop can take any value instead of 6.
i = 0
numbers = []
while i < 6:
numbers.append(i)
i += 1
I created the following script so that I can use the variable(or more specifically argument ) instead of 6 .
def numbers(limit):
i = 0
numbers = []
while i < limit:
numbers.append(i)
i = i + 1
print numbers
user_limit = raw_input("Give me a limit ")
numbers(user_limit)
When I didn't use the raw_input() and simply put the arguments from the script it was working fine but now when I run it(in Microsoft Powershell) a cursor blinks continuously after the question in raw_input() is asked. Then i have to hit CTRL + C to abort it. Maybe the function is not getting called after raw_input().
Now it is giving a memory error like in the pic.
You need to convert user_limit to Int:
raw_input() return value is str and the statement is using i which is int
def numbers(limit):
i = 0
numbers = []
while i < limit:
numbers.append(i)
i = i + 1
print numbers
user_limit = int(raw_input("Give me a limit "))
numbers(user_limit)
Output:
Give me a limit 8
[0, 1, 2, 3, 4, 5, 6, 7]