I have a tuple list which looks like this:
val days= List(("Sunday", 1), ("Monday", 2), ("Tuesday", 1),
("Wednesday", 2), ("Thursday", 3), ("Friday", 2),
("Saturday", 3))
I want the final result to look like this:
"data": [
[
"Sunday, 1",
"Tuesday, 1"
],
[
"Monday, 2",
"Friday, 2"
"Wednesday,2"
],
[
"Thursday, 3",
"Saturday,3"
]
]
You can group and then map values:
days.groupBy(_._2)
.mapValues(_.map { case (name, nr) => s"$name, $nr" } )
.valuesIterator.toList
The result is:
List(List(Monday, 2, Wednesday, 2, Friday, 2), List(Sunday, 1, Tuesday, 1), List(Thursday, 3, Saturday, 3))
P.S.: As Luis Miguel Mejía Suárez suggests, using groupMap (from scala 2.13) can make this a bit more concise and readable:
days.groupMap(_._2) { case (name, nr) => s"$name, $nr" }
.valuesIterator.toList
Related
I'm new to postgREST. I've set it up and it's working fine with my db. I'm going through the docs and I think I could use of Resource Embedding, but I can't figure out how to make it work in a nested way.
My schema has tables similar to the following:
create table ta (
a_id integer primary key,
a_desc varchar(50)
);
create table tb (
b_id integer primary key,
a_id integer not null,
b_desc varchar(50),
constraint tb_fk1 foreign key (a_id) references ta(a_id)
);
create table tc (
c_id integer primary key,
b_id integer not null,
c_desc varchar(50),
constraint tc_fk1 foreign key (b_id) references tb(b_id)
);
insert into ta values (1, 'a1');
insert into tb values (1, 1, 'b1');
insert into tb values (2, 1, 'b2');
insert into tc values (1, 1, 'c1');
insert into tc values (2, 1, 'c2');
insert into tc values (3, 2, 'c3');
insert into tc values (4, 2, 'c4');
Resource embedding works when I select ta an tb:
localhost:3000/ta?select=*,tb(*)
[
{
"a_id": 1,
"a_desc": "a1",
"tb": [
{
"b_id": 1,
"a_id": 1,
"b_desc": "b1"
},
{
"b_id": 2,
"a_id": 1,
"b_desc": "b2"
}
]
}
]
It also works with tb and tc:
localhost:3000/tb?select=*,tc(*)
[
{
"b_id": 1,
"a_id": 1,
"b_desc": "b1",
"tc": [
{
"c_id": 1,
"b_id": 1,
"c_desc": "c1"
},
{
"c_id": 2,
"b_id": 1,
"c_desc": "c2"
}
]
},
{
"b_id": 2,
"a_id": 1,
"b_desc": "b2",
"tc": [
{
"c_id": 3,
"b_id": 2,
"c_desc": "c3"
},
{
"c_id": 4,
"b_id": 2,
"c_desc": "c4"
}
]
}
]
But I don't know how to make it work from ta through tc, kind of combining both queries.
Does anyone know how I could achieve this? Preferably using a query string, but working with views or stored procedures would be ok too.
Thanks in advance for any help on this.
PS: Using Potstgres 12 and postgREST 7
For nested resource embedding, you can do:
GET localhost:3000/ta?select=*,tb(*,tc(*))
I'm quite new to Python and programming in general, so apologies if this is quite basic or has been asked and answered before. Here is a sample of the data I'm working with:
{
"homeTeam": {
"formation": [
"4",
"4",
"2"
],
"lineupsSorted": [
{
"player": {
"name": "Scott P. Brown",
"slug": "scott-p-brown",
"shortName": "S. P. Brown",
"id": 19889,
"hasImage": true
},
"position": 1,
"shirtNumber": 1,
"substitute": false,
"positionName": "Goalkeeper",
"positionNameshort": "G",
"captain": false
},
{
"player": {
"name": "Carl Winchester",
"slug": "carl-winchester",
"shortName": "C. Winchester",
"id": 110785,
"hasImage": true
},
"position": 2,
"shirtNumber": 27,
"substitute": false,
"positionName": "Midfielder",
"positionNameshort": "M",
"captain": false
},
I am looking to automate populating defined names as I have done manually here:
hometeamPositions =['Goalkeeper','Midfielder','Defender','Defender','Defender','Midfielder','Midfielder','Midfielder','Midfielder','Forward','Forward','Goalkeeper','Defender','Defender','Midfielder','Midfielder','Forward','Forward']
hometeamPlayers = ['S. P. Brown','C. Winchester','M. Onariase','W.
Boyle','J. Cranston','H. Pell','J. Rowe','K. Storer','B. Waters','D.
Wright','D. Holman','R. Lovett','J. Barthram','T. Plavotic','J.
Munns','L. Davis','K. Wootton','J. Dayton']
As I will be repeating this process many hundreds of times with different data (same structure) I was wondering if anyone could give me some tips on automatically building these ranges?
Thanks,
Peter
I'm not sure I understood what is the problem you are trying to solve but I'll try to help.
Assuming you have a dictionary team_dict and you want to create 2 list: hometeamPositions and hometeamPlayers you can use the following code:
hometeamPlayers = []
hometeamPositions = []
for player_dict in teams_dict['homeTeam']['lineupsSorted']:
hometeamPlayers.append(player_dict['player']['shortName'])
hometeamPositions.append(player_dict['positionName'])
The output on your example will be:
hometeamPlayers = ['S. P. Brown', 'C. Winchester']
hometeamPositions = ['Goalkeeper', 'Midfielder']
I have two tables:
Ticket Table
id paid_with_tax
1 5
2 6
3 7
TicketAdjustment Table
id ticket_id value_with_tax
1 1 2
2 1 1
3 1 2
4 1 3
5 2 5
The query I use:
use = 0
Ticket.objects.all().annotate(
paid_amount=Sum(
F('paid_with_tax') +
Coalesce(F('ticketadjustment__value_with_tax'), 0) * use
)
)
the query would return the following:
[
{id: 1, paid_amount: 7},
{id: 1, paid_amount: 6},
{id: 1, paid_amount: 7},
{id: 1, paid_amount: 8},
{id: 2, paid_amount: 11},
{id: 3, paid_amount: 7},
]
but the above is incorrect since the Ticket Table id=1 values are duplicated by the TicketAdjustment Table values.
how can i get the query to sum the TicketAdjustment Table values and return the following:
[
{id: 1, paid_amount: 13},
{id: 2, paid_amount: 11},
{id: 3, paid_amount: 7},
]
Here the solution for your problem :
Ticket.objects.all().annotate(
paid_amount=(F('paid_with_tax') +
Sum(Coalesce(F('ticketadjustment__value_with_tax'), 0))
)
).values_list('id', 'paid_amount')
values_list select the field you want in your result.
In your primary request there is a big problem.
Sum(F('paid_with_tax') + Coalesce(F('ticketadjustment__value_with_tax'), 0) * use)
This ligne miltiply value_with_tax with zero. So give you zero. It's like :
Sum(F('paid_with_tax'))
You want the sum of value_with_tax for each ticket, this is why I move Sum on it :
Sum(Coalesce(F('ticketadjustment__value_with_tax'), 0))
And after add the value of paid_with_tax
NB : I remove your variable use, because don't know is goal.
How to nicely convert a data.frame with hierarchical information to a JSON (or nested list)?
Let's say we have the following data.frame:
df <- data.frame(
id = c('1', '1.1', '1.1.1', '1.2'),
value = c(10, 5, 5, 5))
# id value
# 1 10
# 1.1 5
# 1.1.1 5
# 1.2 5
Then I would like to end up with the following JSON:
{
"id": "1",
"value": 10,
"children": [
{
"id": "1.1",
"value": 5,
"children": [
{
"id": "1.1.1",
"value": 5
}
]
},
{
"id": "1.2",
"value": 5
}
]
}
Where id defines the hierarchical structure, and . is a delimiter.
My intention is to easily be able to convert data from R to hierarchical D3 visualisations (e.g. Partition Layout or Zoomable Treemaps). It would also be nice if it is possible to add more "value"-columns; e.g value, size, weight, etc.
Thank you!
EDIT: I reverted to the original question, so it is easier to follow all the answers (sorry for all the editing).
I tend to have RJSONIO installed which does this:
R> df <- data.frame(id = c('1', '1.1', '1.1.1', '1.2'), value = c(10, 5, 5, 5))
R> RJSONIO::toJSON(df)
[1] "{\n \"id\": [ \"1\", \"1.1\", \"1.1.1\", \"1.2\" ],\n\"value\": [ 10, 5, 5, 5 ] \n}"
R> cat(RJSONIO::toJSON(df), "\n")
{
"id": [ "1", "1.1", "1.1.1", "1.2" ],
"value": [ 10, 5, 5, 5 ]
}
R>
That is not your desired output but the desired nesting / hierarchy was not present in the data.frame. I think if you nest a data.frame inside a list you will get there.
Edit: For your revised question, here is the R output of reading you spec'ed JSON back in:
R> RJSONIO::fromJSON("/tmp/foo.json")
$id
[1] "1"
$value
[1] 10
$children
$children[[1]]
$children[[1]]$id
[1] "1.1"
$children[[1]]$value
[1] 5
$children[[1]]$children
$children[[1]]$children[[1]]
$children[[1]]$children[[1]]$id
[1] "1.1.1"
$children[[1]]$children[[1]]$value
[1] 5
$children[[2]]
$children[[2]]$id
[1] "1.2"
$children[[2]]$value
[1] 5
R>
A possible solution.
First I define the following functions:
# Function to get the number hierarchical dimensions (occurences of "." + 1)
ch_dim <- function(x, delimiter = ".") {
x <- as.character(x)
chr.count <- function(x) length(which(unlist(strsplit(x, NULL)) == delimiter))
if (length(x) > 1) {
sapply(x, chr.count) + 1
} else {
chr.count(x) + 1
}
}
# Function to convert a hierarchical data.frame to a nested list
lst_fun <- function(ch, id_col = "id", num = min(d), stp = max(d)) {
# Convert data.frame to character
ch <- data.frame(lapply(ch, as.character), stringsAsFactors=FALSE)
# Get number of hierarchical dimensions
d <- ch_dim(ch[[id_col]])
# Convert to list
lapply(ch[d == num,][[id_col]], function(x) {
tt <- ch[grepl(sprintf("^%s.", x), ch[[id_col]]),]
current <- ch[ch[[id_col]] == x,]
if (stp != num && nrow(tt) > 0) {
c(current, list(children = lst_fun(tt, id_col, num + 1, stp)))
} else { current }
})
}
then convert the data.frame to a list:
lst <- lst_fun(df, "id")
and finally, the JSON:
s <- RJSONIO::toJSON(lst)
I know this is probably a very simple List operation in Scala, but I'm a newbie and can't figure it out. I have a query that returns a result set with a series of values, grouped by a common id. For example:
Result Set:
[{ 1, "a", 30 },
{ 1, "b", 20 },
{ 1, "c", 22 },
{ 2, "a", 32 },
{ 2, "c", 10 }]
and what I'd like to do is put this into a map as such:
1 -> [{"a", 30}, {"b", 20}, {"c", 22}]
2 -> [{"a", 32}, {"c", 10}]
I think the collect method can be used for this but can't figure it out.
I'm not sure what the types in your data structure are, but maybe you can adapt this. This assumes you have a collection of tuples:
val items =
List((1, "a", 30),
(1, "b", 20),
(1, "c", 22),
(2, "a", 32),
(2, "c", 10))
items
.groupBy{ case (a,b,c) => a }
.mapValues(_.map{ case (a,b,c) => (b,c) })
// Map(1 -> List((a,30), (b,20), (c,22)), 2 -> List((a,32), (c,10)))
Or, more succinctly:
items.groupBy(_._1).mapValues(_.map(t => (t._2, t._3)))
The collect method is something else entirely (basically, it's map that drops non-matching values). The groupBy method is what you were really looking for.