Priority Sorting on a column Kusto Query - database

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

Related

Ruby merge a nested array based on inner array's first element [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 months ago.
Improve this question
I have a nested Ruby array:
array = [["id1", "Mike", "a", "aa"],
["id1", "Mike", "a", "bb"],
["id1", "Mike", "a", "cc"],
["id1", "Mike", "b", "aa"],
["id1", "Mike", "b", "bb"],
["id1", "Mike", "b", "cc"],
["id2", "Joe", "a", "aa"],
["id2", "Joe", "a", "bb"],
["id2", "Joe", "a", "cc"],
["id2", "Joe", "b", "aa"],
["id2", "Joe", "b", "bb"],
["id2", "Joe", "b", "cc"],
["id2", "Joe", "c", "aa"],
["id2", "Joe", "c", "bb"],
["id2", "Joe", "c", "cc"]]
I want to merge it based on the first element, with grouping as such:
result = [["id1", "Mike", ["a", "b"], ["aa", "bb", "cc"]],
["id2", "Joe", ["a", "b", "c"], ["aa", "bb", "cc"]]]
What's the best way to do this?
Code
result = array.group_by { |a| [a[0], a[1]] }.map do |k, v|
v.map { |id, name, v1, v2| [v1, v2] }.transpose.map(&:uniq).prepend(*k)
end
p result
Output
[["id1", "Mike", ["a", "b"], ["aa", "bb", "cc"]], ["id2", "Joe", ["a", "b", "c"], ["aa", "bb", "cc"]]]

How do I merge arrays from multiple documents without duplicates in MongoDB aggregation?

I have 3 documents:
{
"id": 1,
"user": "Brian1",
"configs": [
"a",
"b",
"c",
"d"
]
}
----
{
"id": 2,
"user": "max_en",
"configs": [
"a",
"h",
"i",
"j"
]
}
----
----
{
"id": 3,
"user": "userX",
"configs": [
"t",
"u",
"s",
"b"
]
}
I want to merge all the "configs" arrays into one array without dublicates,like this:
{
"configs": [
"a",
"b",
"c",
"d",
"h",
"i",
"j",
"t",
"u",
"s",
]
}
I've tried the following:
Aggregation.group("").addToSet("configs").as("configs") and { _id: "", 'configs': { $addToSet: '$configs' } }
The first one gives an error because I've left the fieldname empty (I don't know what to put there).
The second one returns a merged array but with duplicates.
When you want to group all the documents, you need to add {_id: null}
It means group all documents.
Probably you need this
db.collection.aggregate([
{
"$unwind": "$configs"
},
{
$group: {
_id: null,
configs: {
"$addToSet": "$configs"
}
}
}
])
But be cautious when you need to use on larger collection without a match.

JQ how to merge multiple objects in an array into one

A little more sophisticated as my question mentioned below.
I learned to use arrays more, but it screws things up too.
Input:
{
"a": [
{
"b": "c",
"d": "e"
},
{
"b": "f",
"d": "g"
}
],
"h": [
{
"b": "c",
"i": "j"
},
{
"b": "f",
"i": "k"
}
]
}
desired output:
{
"l": [
{
"b": "c",
"d": "e",
"i": "j"
},
{
"b": "f",
"d": "g",
"i": "k"
}
]
}
Things that I've tried, based up on JQ How to merge multiple objects into one
{ x: [ inputs | .a[] | { (.h[]): .i } ] | add}
The key to a simple solution is transpose:
[.a, .h]
| transpose
| map(add)
| {l: .}

Adding parameters to Array Product function in Ruby

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

turn array columns into rows ruby [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have an array of arrays called puzzle and I'm trying to return a new array with the first array consisting of
["a", "s", "i", "o", "s", "u", "z"]
Then the next array consisting of the array"s second index
["k", "o", "t", "t", "e", "r", "s"]
etc etc. What are some good ways to do this. I was thinking of using map and two counters but could not get them to operate or or increase at different times properly. Any help would be awesome. Thanks!
I want to return a new array from this puzzle:
puzzle = [
["a", "k", "f", "o", "x", "e", "s"],
["s", "o", "a", "w", "a", "h", "p"],
["i", "t", "c", "k", "e", "t", "n"],
["o", "t", "s", "d", "h", "o", "h"],
["s", "e", "x", "g", "s", "t", "a"],
["u", "r", "p", "i", "w", "e", "u"],
["z", "s", "b", "n", "u", "i", "r"]
]
Array#transpose is there for you:
puzzle = [
["a", "k", "f", "o", "x", "e", "s"],
["s", "o", "a", "w", "a", "h", "p"],
["i", "t", "c", "k", "e", "t", "n"],
["o", "t", "s", "d", "h", "o", "h"],
["s", "e", "x", "g", "s", "t", "a"],
["u", "r", "p", "i", "w", "e", "u"],
["z", "s", "b", "n", "u", "i", "r"]
]
puzzle.transpose
# => [["a", "s", "i", "o", "s", "u", "z"],
# ["k", "o", "t", "t", "e", "r", "s"],
# ["f", "a", "c", "s", "x", "p", "b"],
# ["o", "w", "k", "d", "g", "i", "n"],
# ["x", "a", "e", "h", "s", "w", "u"],
# ["e", "h", "t", "o", "t", "e", "i"],
# ["s", "p", "n", "h", "a", "u", "r"]]
class Array
def my_transpose!
size.times do |i|
0.upto(i) do |j| # iterate only through lower half
self[i][j], self[j][i] = self[j][i], self[i][j] # swap rows and cols
end
end
self # return the array itself
end
def my_transpose
dup.map(&:dup).my_transpose! # inner arrays are dup'ed, too
end
end
OR if you don't need a mutator....
.transpose method then pick the array you want with []
puzzle.transpose[0]
The [0] says give me the first result.
puzzle.transpose[0]
=> ["a", "s", "i", "o", "s", "u", "z"]
puzzle.transpose[1]
=> ["k", "o", "t", "t", "e", "r", "s"]

Resources