jq grab keys from array of objects - jq

Let's say I have the following array:
[
{
"a": 1,
"b": 2,
"c": 3,
"d": 4
},
{
"a": 10,
"b": 20,
"c": 30,
"d": 40
},
{
"a": 100,
"b": 200,
"c": 300,
"d": 400
}
]
I want to generate a new array with just the a and b keys. I know I can do it like this:
ARRAY | jq '. | map({ a: .a, b: .b })'
I'm not renaming any of the keys so having to type a and b seems a bit verbose. Is there a cleaner way to do this?

You will have to type a and b once in order to specify which ones to keep:
jq 'map({a,b})'
Alternatively, specify what to delete, here .c and .d:
jq 'map(del(.c,.d))'
In any case, .| is also superfluous.

Related

Ansible - keys missing after changing values in a dict

I want to change all the values "b" in a way that I will divide it with some number.
Here is the code:
- name: code
hosts: localhost
gather_facts: false
vars:
dict1: [{"a": 1, "b": 2, "c": 3}, {"a": 5, "b": 5, "c": 6},{"a": 8, "b": 9, "c": 10}]
dict2: |
[
{% for i in dict1 %}
{{ i.a, (i.b/2)|int, i.c }},
{% endfor %}
]
tasks:
- debug:
var: dict2|type_debug
- debug:
var: dict2
Problem with this is that I've got just values and "keys" are missing
ok: [localhost] => {
"dict2": [
[
1,
1,
3
],
[
5,
2,
6
],
[
8,
4,
10
]
]
What should I change to include keys too?
Also, not that important, but I've got [ ] instead { } for each item in the loop (simple replacement [] with {} in the variable dict2 doesn't work).
Thanks!
The variable dict1 is a list of dicts. This means that you cannot simply define a list of values, but must also create a dict again.
There are surely different approaches for this, one is the following:
dict1: [{"a": 1, "b": 2, "c": 3}, {"a": 5, "b": 5, "c": 6},{"a": 8, "b": 9, "c": 10}]
dict2: |
[
{% for i in dict1 %}
{{ dict( ['a', 'b', 'c'] | zip( [i.a, (i.b/2)|int, i.c] ) ) }},
{% endfor %}
]
a list with the values a, b and c is defined
another list with the values for a, b, c is created
both lists are connected by zip().
the resulting zip lists are converted to a dict by dict().
The result of - debug: var=dict2 looks like this:
TASK [debug] **********************
ok: [localhost] => {
"dict2": [
{
"a": 1,
"b": 1,
"c": 3
},
{
"a": 5,
"b": 2,
"c": 6
},
{
"a": 8,
"b": 4,
"c": 10
}
]
}

dealing with lists and arrays when using toJson function - in R

I am working with a pre-specified API definition, which I need to adhere to:
"myTable": {
"split": [
{
"total": 0,
"perItem": [
0,
0,
0
]
}
]
the results from my function are a list (since I am using an apply):
Export
[[1]]
[[1]]$total
[1] 13
[[1]]$perItem
1 2 3
5 7 0
but when I convert this to .json, it is not the same format as the predefined API definition:
toJSON(Export)
[{"total":[13],"perPlan":[5,7,0]}]
I was wondering how I can convert the output of the apply to have the predefined API?
I tried converting this to array:
toJSON(array(Export), simplify = TRUE)
[{"total":[13],"perPlan":[5,7,0]}]
but this still has the additional [] around the content of total.
According to the API specification your input should also "embed" your data into this split and mytable list, which can be done with:
Export <- list(list(total = 13,
perItem = c(5, 7, 0)))
for_JSON <- list(mytable = list(split = Export))
toJSON(for_JSON, simplify = TRUE, pretty = TRUE)
which gives:
{
"mytable": {
"split": [
{
"total": 13,
"perItem": [5, 7, 0]
}
]
}
}
This looks like what the API wants.

Creating a counter from a dictionary

I'm new to learning python! I can't figure this out. The goal of this programme is to see how many keys there are in a given dictionary and count the amount of unique keys. The value of the key is irrelevant.
Input:
list = {"A": "apples", "B":"apples", "A":"bananas", "D":"oranges","A":"grapes", "B": "bananas", "C": "apples"}
count = {}
for i in list.keys():
count.get(i,0)
count[i] = count.get(i,0) + 1
print(count)
What I want is this:
{'A': 3, 'B': 2, 'C': 1, 'D': 1}
However I get this:
{'A': 1, 'B': 1, 'D': 1, 'C': 1}
Why does this happen and how can I solve this?
You're getting this because when you make the dictionary a list, it removes all the duplicate elements.
I'll try and find a solution.
EDIT: Are your values randomized?

Elixir Get Map containing maximum values of specific field

I'm a beginner in Elixir programming language.
I have an object something like this:
{
id: uuid,
created_at: DateTime.t,
updated_at: DateTime.t,
type: my_type
}
let's say my_type is one of ~w[A B C D]
I want to write a function which takes a list of these objects and returns a following map:
%{
A: 120,
B: 220,
C: 560,
D: 0,
any: 560
}
The values here has to be the MAXIMUM difference between updated_at and created_at columns(Timex.diff(updated_at, created_at, :seconds)) per my_type + any in addition.
In case of any the my_type is not considered and takes the maximum among all objects in the list.
What is the best way to do it in Elixir? Thanks.
The following will group the list by its type, then calculate the max difference for each group, and finally result in a map containing each type as the key and max difference as the value.
map = list
|> Enum.group_by(& &1.type)
|> Enum.map(fn {type, values} ->
max =
values
|> Enum.map(fn %{created_at: created_at, updated_at: updated_at} ->
# return the difference here
end)
|> Enum.max
{type, max}
end)
|> Map.new
This should give you something like:
%{
A: 120,
B: 220,
C: 560,
D: 0
}
You can calculate the value for any now by doing map |> Map.values |> Enum.max.
I am posting this here for the sake of formatting and diversity. The answer by #Dogbert is likely better fit, although this approach could be more straightforward and arguably flexible.
list = [%{type: :a, v1: 10, v2: 20},
%{type: :a, v1: 10, v2: 30},
%{type: :b, v1: 10, v2: 20},
%{type: :c, v1: 10, v2: 20}]
kw = for %{type: t, v1: v1, v2: v2} <- list,
do: {t, v2 - v1}, into: []
#⇒ [a: 10, a: 20, b: 10, c: 10]
kw
|> Enum.sort_by(fn {_, v} -> v end, &>=/2)
|> Enum.uniq_by(fn {k, _} -> k end)
#⇒ [a: 20, b: 10, c: 10]

VisJS graph2d draw order / groupOrder

Is there an equivalent groupOrder option for graph2d as there is for the timeline widget? http://visjs.org/docs/timeline/#Configuration_Options
Looking to draw bar charts in a specific order to handle overlapping.
The group order is determined by the order how you add groups, unless you set the ids as integers.
This is a example where you set the ids with strings:
a = new vis.DataSet()
-> DataSet {_options: Object, _data: Object, length: 0, _fieldId: "id", _type: Object…}
a.add([{id:"b"}, {id: "a"}, {id: "c"}])
-> ["b", "a", "c"]
a.getIds()
-> ["b", "a", "c"]
But when you create a dataset where the ids are integers, it will sort the datagroups based on the integers:
b = new vis.DataSet()
-> DataSet {_options: Object, _data: Object, length: 0, _fieldId: "id", _type: Object…}
b.add([{id:2}, {id: 3}, {id: 1}])
-> [2, 3, 1]
b.getIds()
-> [1, 2, 3]
When you mix the integers and strings it will sort the integers first and then then leave the strings unsorted.
c = new vis.DataSet()
DataSet {_options: Object, _data: Object, length: 0, _fieldId: "id", _type: Object…}
c.add([{id:"b"}, {id: 2}, {id: "a"} , {id: 1}])
["b", 2, "a", 1]
c.getIds()
[1, 2, "b", "a"]

Resources