Scenario: Players can be marked with the status winner, tied, or loser. The priorities of the status is as such: If a player is ever "tied", they can't be a "loser", if they are ever a "winner", they can't be a "loser" or "tied". Table 1 has error rows recorded but the desired table should display the players and their up-to-date status and the timestamp of the most recent correct records. Is this something that is doable with Kusto? I can select the most recent by timestamp with the query below. I am unsure how to compare. I've started looking at the prev() function but I'm not certain this will do what I want in terms of comparing based on a priority. (https://learn.microsoft.com/en-us/azure/data-explorer/kusto/query/prevfunction)
let T1 = datatable(player:string, status:string, timestamp:datetime)
[
"A", "winner", datetime(2020-11-24 08:00),
"A", "winner", datetime(2020-11-24 10:00),
"B", "tied", datetime(2020-11-24 09:00),
"B", "tied", datetime(2020-11-24 11:00),
"B", "tied", datetime(2020-11-24 14:00),
"B", "loser", datetime(2020-11-24 15:00),
"C", "loser", datetime(2020-11-24 08:00),
"C", "loser", datetime(2020-11-24 10:00),
"C", "loser", datetime(2020-11-24 11:00),
"C", "loser", datetime(2020-11-24 13:00),
"C", "tied", datetime(2020-11-24 14:00),
"C", "winner", datetime(2020-11-24 15:00),
"D", "winner", datetime(2020-11-24 07:00),
"D", "winner", datetime(2020-11-24 11:00),
"D", "winner", datetime(2020-11-24 16:00),
"D", "tied", datetime(2020-11-24 21:00),
"E", "tied", datetime(2020-11-24 09:00),
"E", "tied", datetime(2020-11-24 11:00),
"E", "loser", datetime(2020-11-24 13:00),
"E", "tied", datetime(2020-11-24 18:00),
"F", "loser", datetime(2020-11-24 10:00),
"F", "loser", datetime(2020-11-24 11:00),
"F", "loser", datetime(2020-11-24 18:00),
"G", "loser", datetime(2020-11-24 11:00),
"G", "tied", datetime(2020-11-24 14:00),
"G", "loser", datetime(2020-11-24 16:00),
"G", "tied", datetime(2020-11-24 18:00),
"G", "loser", datetime(2020-11-24 21:00),
]
;
T1
| summarize arg_max(timestamp, *) by player
| order by player asc
result:
player| timestamp | status
_____________________________________________
A | 2020-11-24 10:00:00.0000000 | winner
B | 2020-11-24 15:00:00.0000000 | loser
C | 2020-11-24 15:00:00.0000000 | winner
D | 2020-11-24 21:00:00.0000000 | tied
E | 2020-11-24 18:00:00.0000000 | tied
F | 2020-11-24 18:00:00.0000000 | loser
G | 2020-11-24 21:00:00.0000000 | loser
H | 2020-11-24 21:00:00.0000000 | loser
final desired result table:
player| timestamp | status
_____________________________________________
A | 2020-11-24 10:00:00.0000000 | winner
B | 2020-11-24 14:00:00.0000000 | tied
C | 2020-11-24 15:00:00.0000000 | winner
D | 2020-11-24 16:00:00.0000000 | winner
E | 2020-11-24 18:00:00.0000000 | tied
F | 2020-11-24 18:00:00.0000000 | loser
G | 2020-11-24 18:00:00.0000000 | tied
H | 2020-11-24 09:00:00.0000000 | winner
If I understand your question correctly, the following could work.
Calculate the aggregated status per player, according the logic you've provided (using make_set() and array_index_of().
Find the max. timestamp per player/state, using a join
let T =
datatable(player: string, status: string, timestamp: datetime)
[
"A", "winner", datetime(2020-11-24 08:00),
"A", "winner", datetime(2020-11-24 10:00),
"B", "tied", datetime(2020-11-24 09:00),
"B", "tied", datetime(2020-11-24 11:00),
"B", "tied", datetime(2020-11-24 14:00),
"B", "loser", datetime(2020-11-24 15:00),
"C", "loser", datetime(2020-11-24 08:00),
"C", "loser", datetime(2020-11-24 10:00),
"C", "loser", datetime(2020-11-24 11:00),
"C", "loser", datetime(2020-11-24 13:00),
"C", "tied", datetime(2020-11-24 14:00),
"C", "winner", datetime(2020-11-24 15:00),
"D", "winner", datetime(2020-11-24 07:00),
"D", "winner", datetime(2020-11-24 11:00),
"D", "winner", datetime(2020-11-24 16:00),
"D", "tied", datetime(2020-11-24 21:00),
"E", "tied", datetime(2020-11-24 09:00),
"E", "tied", datetime(2020-11-24 11:00),
"E", "loser", datetime(2020-11-24 13:00),
"E", "tied", datetime(2020-11-24 18:00),
"F", "loser", datetime(2020-11-24 10:00),
"F", "loser", datetime(2020-11-24 11:00),
"F", "loser", datetime(2020-11-24 18:00),
"G", "loser", datetime(2020-11-24 11:00),
"G", "tied", datetime(2020-11-24 14:00),
"G", "loser", datetime(2020-11-24 16:00),
"G", "tied", datetime(2020-11-24 18:00),
"G", "loser", datetime(2020-11-24 21:00),
]
;
T
| summarize make_set(status) by player
| project player, status = case(array_index_of(set_status, "winner") > -1, "winner",
array_index_of(set_status, "tied") > -1, "tied",
"loser")
| join (
T
| summarize timestamp = max(timestamp) by player, status
) on player, status
| project player, timestamp, status
So I've been scratching my head trying to find a solution to this.
I need a method that will take any number of arrays that I need to collect the product of.
1 array:
return [A, B, C] # => [A, B, C]
2 arrays:
return [A, B, C].product([1, 2, 3]) # => [[A, 1], [A, 2], [A, 3], [B, 1] ... [C, 3]]
3 arrays:
return [A, B, C].product([1, 2, 3,],[x, y, z]) # => [[A, 1, x], [A, 1, y], ... [C, 3, z]]
So my current solution is this case switch, which is functional but inconvenient.
case options.count
when 1
options[0].values
when 2
options[0].values.product(options[1].values)
when 3
options[0].values.product(options[1].values,
options[2].values)
when 4
options[0].values.product(options[1].values,
options[2].values,
options[3].values)
end
What I'm looking for is a method that procedurally or recursively returns the product of an unknown number of arrays. The output needs to be like the above arrays.
I've tried:
array = options[0].values
options.each_with_index do |option, i|
array = array.product(option.values) if i > 0
end
return array
But it returns:
[[[A, 1], x], [[A, 1], y], [[A, 1], z], [[A, 2], x], ... [[C, 3], z]]
Which groups the values incorrectly.
How about something like:
def multi_product(base, *args)
base.product(*args)
end
results:
multi_product(['A', 'B', 'C'])
# => [["A"], ["B"], ["C"]]
multi_product(['A', 'B', 'C'], [1, 2, 3])
# => [["A", 1], ["A", 2], ["A", 3], ["B", 1], ["B", 2], ["B", 3], ["C", 1], ["C", 2], ["C", 3]]
multi_product(['A', 'B', 'C'], [1, 2, 3], ['x', 'y', 'z'])
# => [["A", 1, "x"], ["A", 1, "y"], ["A", 1, "z"], ["A", 2, "x"], ["A", 2, "y"], ["A", 2, "z"], ["A", 3, "x"], ["A", 3, "y"], ["A", 3, "z"], ["B", 1, "x"], ["B", 1, "y"], ["B", 1, "z"], ["B", 2, "x"], ["B", 2, "y"], ["B", 2, "z"], ["B", 3, "x"], ["B", 3, "y"], ["B", 3, "z"], ["C", 1, "x"], ["C", 1, "y"], ["C", 1, "z"], ["C", 2, "x"], ["C", 2, "y"], ["C", 2, "z"], ["C", 3, "x"], ["C", 3, "y"], ["C", 3, "z"]]
multi_product(['A', 'B', 'C'], [1, 2, 3], ['x', 'y', 'z'], [4, 5, 6])
# => [["A", 1, "x", 4], ["A", 1, "x", 5], ["A", 1, "x", 6], ["A", 1, "y", 4], ["A", 1, "y", 5], ["A", 1, "y", 6], ["A", 1, "z", 4], ["A", 1, "z", 5], ["A", 1, "z", 6], ["A", 2, "x", 4], ["A", 2, "x", 5], ["A", 2, "x", 6], ["A", 2, "y", 4], ["A", 2, "y", 5], ["A", 2, "y", 6], ["A", 2, "z", 4], ["A", 2, "z", 5], ["A", 2, "z", 6], ["A", 3, "x", 4], ["A", 3, "x", 5], ["A", 3, "x", 6], ["A", 3, "y", 4], ["A", 3, "y", 5], ["A", 3, "y", 6], ["A", 3, "z", 4], ["A", 3, "z", 5], ["A", 3, "z", 6], ["B", 1, "x", 4], ["B", 1, "x", 5], ["B", 1, "x", 6], ["B", 1, "y", 4], ["B", 1, "y", 5], ["B", 1, "y", 6], ["B", 1, "z", 4], ["B", 1, "z", 5], ["B", 1, "z", 6], ["B", 2, "x", 4], ["B", 2, "x", 5], ["B", 2, "x", 6], ["B", 2, "y", 4], ["B", 2, "y", 5], ["B", 2, "y", 6], ["B", 2, "z", 4], ["B", 2, "z", 5], ["B", 2, "z", 6], ["B", 3, "x", 4], ["B", 3, "x", 5], ["B", 3, "x", 6], ["B", 3, "y", 4], ["B", 3, "y", 5], ["B", 3, "y", 6], ["B", 3, "z", 4], ["B", 3, "z", 5], ["B", 3, "z", 6], ["C", 1, "x", 4], ["C", 1, "x", 5], ["C", 1, "x", 6], ["C", 1, "y", 4], ["C", 1, "y", 5], ["C", 1, "y", 6], ["C", 1, "z", 4], ["C", 1, "z", 5], ["C", 1, "z", 6], ["C", 2, "x", 4], ["C", 2, "x", 5], ["C", 2, "x", 6], ["C", 2, "y", 4], ["C", 2, "y", 5], ["C", 2, "y", 6], ["C", 2, "z", 4], ["C", 2, "z", 5], ["C", 2, "z", 6], ["C", 3, "x", 4], ["C", 3, "x", 5], ["C", 3, "x", 6], ["C", 3, "y", 4], ["C", 3, "y", 5], ["C", 3, "y", 6], ["C", 3, "z", 4], ["C", 3, "z", 5], ["C", 3, "z", 6]]
What it does is take one required parameter (base) which responds to product and then the *args takes a variable number of other parameters and stores them in an array args. You can then use * to deconstruct an array back into an argument list, which is done inside the call to product(*args) so that (in the case of the second example) ends up looking like
['A', 'B', 'C'].product([1, 2, 3], ['x', 'y', 'z'])
Hope this helps
a = [["a", "b", "c"], ["d", "e", "f"], ["g", "h", "i"]]
a[0].product(*a[1..a.length])
#=> [["a", "d", "g"], ["a", "d", "h"], ["a", "d", "i"], ["a", "e", "g"], ["a", "e", "h"], ["a", "e", "i"], ["a", "f", "g"], ["a", "f", "h"], ["a", "f", "i"], ["b", "d", "g"], ["b", "d", "h"], ["b", "d", "i"], ["b", "e", "g"], ["b", "e", "h"], ["b", "e", "i"], ["b", "f", "g"], ["b", "f", "h"], ["b", "f", "i"], ["c", "d", "g"], ["c", "d", "h"], ["c", "d", "i"], ["c", "e", "g"], ["c", "e", "h"], ["c", "e", "i"], ["c", "f", "g"], ["c", "f", "h"], ["c", "f", "i"]]
# or
a.slice!(0).product(*a) #Note: this mutates array.
# or
a[0].product(*a.drop(1)) # suggested by Cary Swoveland
I have an array of array as below:
a = [
["a", "v", 1], ["b", "w", 2], ["c", "x", 1], ["d", "y", 1],
["e", "z", 2], ["f", "one" , 3 ], ["g", "two" , 3 ], ["g", "one" , 4 ],
["f", "one" , 1 ], ["h", "one" , 5 ], ["f", "one" , 4 ],
# ...
]
Then , i expect the result as 5 different arrays
a1 = [ ["a", "v", 1],["c", "x", 1], ["d", "y", 1], ["f", "one" , 1 ] ]
a2 = [ ["b", "w", 2], ["e", "z", 2] ]
a3 = [ ["f", "one", 3], ["g", "two", 3] ]
a4 = [ ["g", "one", 4], ["f", "one", 4] ]
a5 = [ ["h", "one" , 5 ] ]
# ...
an = []
By doing the below code, i was able to sort it.
b = a.sort{|c,d|c[2] <=> d[2]}
How can i generate such a list.
Please help.Thanks in advance.
You could use partition:
a = [["a", "v", 1], ["b", "w", 2], ["c", "x", 1], ["d", "y", 1], ["e", "z", 2]]
a1, a2 = a.partition { |e| e[2] == 1 }
a1 #=> [["a", "v", 1], ["c", "x", 1], ["d", "y", 1]]
a2 #=> [["b", "w", 2], ["e", "z", 2]]
With more than 2 values, you could use group_by:
a = [
["a", "v", 1], ["b", "w", 2], ["c", "x", 1], ["d", "y", 1],
["e", "z", 2], ["f", "one" , 3 ], ["g", "two" , 3 ], ["g", "one" , 4 ],
["f", "one" , 1 ], ["h", "one" , 5 ], ["f", "one" , 4 ]
]
hash = a.group_by { |e| e[2] }
#=> { 1=>[["a", "v", 1], ["c", "x", 1], ["d", "y", 1], ["f", "one", 1]],
# 2=>[["b", "w", 2], ["e", "z", 2]],
# 3=>[["f", "one", 3], ["g", "two", 3]],
# 4=>[["g", "one", 4], ["f", "one", 4]],
# 5=>[["h", "one", 5]] }
To access the arrays, you can use hash[1], hash[2], etc. or you can assign them to variables:
a1, a2, a3, a4, a5 = hash.values_at(1, 2, 3, 4, 5)
a1 #=> [["a", "v", 1], ["c", "x", 1], ["d", "y", 1], ["f", "one", 1]]
a2 #=> [["b", "w", 2], ["e", "z", 2]]
a3 #=> [["f", "one", 3], ["g", "two", 3]]
a4 #=> [["g", "one", 4], ["f", "one", 4]]
a5 #=> [["h", "one", 5]]
Select would be the more readable option:
a.select do |v| v.third == 1 end
=> [["a", "v", 1], ["c", "x", 1], ["d", "y", 1]]