Combine LINQ results having most common attributes - linq

I have a Linq query:
var result = (from m in hl7Messages
join d in _esprEFContextProvider.Context.HL7Diagnosis
on m.MessageControlID_Guid equals d.MessageControlID
join i in _esprEFContextProvider.Context.HL7Insurance
on m.MessageControlID_Guid equals i.MessageControlID
select new
{
patientName = m.PatientFirstname + " " + m.PatientMiddleName + " " + m.PatientLastname,
m.PatientAccountNumber,
i.PlanType,
m.AssignedPatientLocation,
d.DxDescription,
m.AdmitDate
}).ToList();
and this is the result:
{
patientName: "Mike Mikey",
patientAccountNumber: "111111111",
planType: "Medicare A",
assignedPatientLocation: "1st Floor",
dxDescription: "Chest Pain",
admitDate: "5/17/14 11:46 PM"
},
{
patientName: "Mike Mikey",
patientAccountNumber: "111111111",
planType: "Medicare A",
assignedPatientLocation: "1st Floor",
dxDescription: "Heart Failure",
admitDate: "5/17/14 11:46 PM"
}
i want this:
{
patientName: "Mike Mikey",
patientAccountNumber: "111111111",
planType: "Medicare A",
assignedPatientLocation: "1st Floor",
dxDescription: "Heart Failure, Chest Pain",
admitDate: "5/17/14 11:46 PM"
}
Can anyone please tell me how?

You could create a grouping on the allPatients or result to create a List of Description per patients then you could join this to another LINQ query
var patientAndDescriptionList = from p in allPatients
group p.DxDescription by p.PatientAccountNumber into g
select new { PatientAccountNumber = g.Key, DescriptionList = g.ToList() // note could flatten to String with String.Join(g.ToList(),",")
};

Related

Group/Sort output of a Join LINQ query based on multiple columns

I'm trying to output results of a LINQ query in groups. All list items are strings. The string to join the two lists on is AssociatedCase. The two lists are:
InternalIssue - {Id, Key, ReadMe, AssociatedCase}
{"44", "INT-44", "this is the read me for 44", "1234"}
{"54", "INT-54", "this is the read me for 54", "1234"}
{"54", "INT-54", "this is the read me for 54", "5678"}
{"55", "INT-55", null, "9999"}
ExternalCase - {CaseName, Account, Contact, AssociatedCase}
{"EXC-222", "1234", "Nike", "Nancy"}
{"EXC-111", "5678", "Reebok", "Amber"}
{"EXC-000", "9999", "Puma", "Susan"}
I've tried suggestions from similar posts but am unable to make it work - usually some of the list items become inaccessible when I start trying to group and join the lists together.
var query = issueList.Join(caseList,
i => i.AssociatedCase,
c => c.AssociatedCase,
(i, c) => new
{
i.Key,
i.ReadMe,
c.CaseName,
c.Account,
c.Contact
});
foreach (var issue in query)
{
Console.WriteLine($"{issue.Key} - {issue.ReadMe}\n" +
$"\t{issue.CaseName} - {issue.Account}, {issue.Contact}");
}
This is what I want:
(INT-44) - this is the read me for 44
(EXC-222) - Nike, Nancy
(INT-54) - this is the read me for 54
(EXC-111) - Reebok, Amber
(EXC-222) - Nike, Nancy
(INT-55) -
(EXC-000) - Puma, Susan
... but this is what I get:
(INT-44) - this is the read me for 44
(EXC-222) - Nike, Nancy
(INT-54) - this is the read me for 54
(EXC-222) - Nike, Nancy
(INT-54) - this is the read me for 54
(EXC-111) - Reebok, Amber
(INT-55) -
(EXC-000) - Puma, Susan
Need to group data after join:
var issueList = new[]
{
new {Id = "44", Key = "INT-44", ReadMe = "this is the read me for 44", AssociatedCase = "1234"},
new {Id = "54", Key = "INT-54", ReadMe = "this is the read me for 54", AssociatedCase = "1234"},
new {Id = "54", Key = "INT-54", ReadMe = "this is the read me for 54", AssociatedCase = "5678"},
new {Id = "55", Key = "INT-55", ReadMe = (string) null, AssociatedCase = "9999"}
};
var caseList = new[]
{
new {CaseName = "EXC-222", AssociatedCase = "1234", Account = "Nike", Contact = "Nancy"},
new {CaseName = "EXC-111", AssociatedCase = "5678", Account = "Reebok", Contact = "Amber"},
new {CaseName = "EXC-000", AssociatedCase = "9999", Account = "Puma", Contact = "Susan"}
};
var query = issueList
.Join(caseList,
o => o.AssociatedCase,
i => i.AssociatedCase,
(issue, #case) => (issue, #case))
.GroupBy(v => v.issue.Key)
.Select(v => new
{
v.Key,
v.First().issue.ReadMe,
cases = v
.Select(i => new
{
i.#case.CaseName,
i.#case.Account,
i.#case.Contact
})
.OrderBy(c => c.CaseName)
.ToArray()
})
.ToArray();
foreach (var item in query)
{
Console.WriteLine($"{item.Key} - {item.ReadMe}");
foreach (var #case in item.cases)
{
Console.WriteLine($"\t{#case.CaseName} - {#case.Account}, {#case.Contact}");
}
}
/*
result:
INT-44 - this is the read me for 44
EXC-222 - Nike, Nancy
INT-54 - this is the read me for 54
EXC-111 - Reebok, Amber
EXC-222 - Nike, Nancy
INT-55 -
EXC-000 - Puma, Susan
*/

LINQ not trivial Group By

I have the following classes (omit syntax errors please)
class Message {
public Person Recipient
...
}
class Person {
public List<Group> Groups
...
}
class Group {
public GroupTypesEnum GroupType
...
}
I want to generate a count of messages by group type.
Example:
Message "hello", to "Person A", which is in "Group X" (type T1), "Group Y" (type T2)
Message "blah", to "Person B", which is in "Group Z" (type T1)
The query that I need would output:
Group type: T1, message count: 2
Group type: T2, message count: 1
How can I achieve this in Linq To Entities?
considering that a person might be in zero groups
I know how to achieve this in memory, but I want to use Linq-To-Entities:
Dictionary<GroupTypesEnum, int> count = new ...
foreach (Message msg in db.Messages) {
foreach (Group group in msg.Recipient.Groups) {
count[group.GroupType]++;
}
}
This is not so hard with SelectMany
var result = messages
.SelectMany(m => m.Recipient.Groups)
.GroupBy(t => t.GroupType)
.Select(g => new { gType = g.Key, count = g.Count()});
Then result.Dump() - in LinqPad
Full source for my test code is here: https://gist.github.com/hoganlong/5841555

How to select attribute in RavenDB Index in Json-Linq?

In RavenDB my document (ID = 1234) is
"datacontainer": {
"data": [
{
"#idx": "1",
"#idy": "a",
"value": {
"#text": "test 2010"
}
},
{
"#idx": "2",
"#idy": "b",
"value": {
"#text": "test 2011"
}
},
{
"#idx": "3",
"#idy": "c",
"value": {
"#text": "test 2012"
}
}
]
}
I want to create an Index, where I choose my favourite values (for example idx = "2" and idy = "b") and the output will be:
(ID, value_text) = (1234, "test 2011")
Now I can select a single element and check its value in Linq:
where p.datacontainer.data[0]["#idx"] == "2" && p.datacontainer.data[0]["#idy"] == "b"
How can I search the right element in my list?
Luigi,
In RavenDB, you don't search for a list value, you are searching for a document with a given document that matches the query you have.
In your case, what does your entity looks like?
I solved my problem! In RavenDB the index, called "MyIndex", is:
Map:
from p in docs
select new
{ Id = p.id,
M = p.dataApplication.datacontainer.data.Where(x => x["#idx"] == "2").First(x => x["#idy"] == "b").value["#text"]
};
Reduce:
from test in results
group test by new {test.Id, test.M } into g
select new { g.Key.Id, g.Key.M }
Now I can use this Index in my queries, so I will search for a document that contains a particular value, for example:
var results = from p in session.Query<QueryResult>("MyIndex")
where p.M == "test 2011"
select p;
Maybe there is a better solution, but now it works!

How can I create a data set with filler rows in linq?

If I have a list like this:
var teams = new List() { "Team A", "Team B", "Team C" };
And I have a data set with scores like this:
var scores = new List<scoredata> {
new scoredata() { Team = 'Team A', Date = '1/1/2012', Value = 1 },
new scoredata() { Team = 'Team B', Date = '1/1/2012', Value = 1 },
new scoredata() { Team = 'Team C', Date = '1/1/2012', Value = 1 },
new scoredata() { Team = 'Team A', Date = '1/2/2012', Value = 2 },
new scoredata() { Team = 'Team B', Date = '1/3/2012', Value = 3 },
new scoredata() { Team = 'Team C', Date = '1/4/2012', Value = 4 }
}
Is it possible to construct a data set that looks like this?
Team A, '1/1/2012', 1
Team B, '1/1/2012', 1
Team C, '1/1/2012', 1
Team A, '1/2/2012', 2
Team B, '1/2/2012', null
Team C, '1/2/2012', null
Team A, '1/3/2012', null
Team B, '1/3/2012', 3
Team C, '1/3/2012', null
Team A, '1/4/2012', null
Team B, '1/4/2012', null
Team C, '1/4/2012', 4
I'm not sure what this is called, but I want to fill out blank dates and scores in my final dataset so that it always returns all Teams for each date, but if score data is not available returns null.
var dates = scores.Select(s => s.Date).Distinct();
var result =
from date in dates
from team in teams
let teamScores = scores.Where(s => s.Team == team && s.Date == date)
orderby date
select new { team, date, Score = teamScores.FirstOrDefault() };
Didn't check with compiler though, give it a try.
Using pure LINQ to Objects.
public class ScoreData
{
public string Team { get; set; }
public string Date { get; set; }
public int? Value { get; set; }
}
var teams = new[] { "Team A", "Team B", "Team C" };
var scores = new[]
{
new ScoreData { Team = "Team A", Date = "1/1/2012", Value = 1 },
new ScoreData { Team = "Team B", Date = "1/1/2012", Value = 1 },
new ScoreData { Team = "Team C", Date = "1/1/2012", Value = 1 },
new ScoreData { Team = "Team A", Date = "1/2/2012", Value = 2 },
new ScoreData { Team = "Team B", Date = "1/3/2012", Value = 3 },
new ScoreData { Team = "Team C", Date = "1/4/2012", Value = 4 },
};
var dates = scores.Select(score => score.Date).Distinct();
var query =
from date in dates
from team in teams
join score in scores
on new { Team = team, Date = date }
equals new { score.Team, score.Date }
into filteredScores
let defaultScore = new ScoreData
{
Team = team,
Date = date,
Value = null,
}
from score in filteredScores.DefaultIfEmpty(defaultScore)
select score;
Note, this most likely won't work as-is in LINQ to SQL or LINQ to Entities, it will need some tweaks.

Using Linq to determine the missing combination of records

Let me start to explain with an example.
var vProducts = new[] {
new { Product = "A", Location ="Y", Month = "January", Demand = 50 },
new { Product = "A", Location ="Y", Month = "February", Demand = 100 },
new { Product = "A", Location ="Y", Month = "March", Demand = 20 },
new { Product = "A", Location ="Y", Month = "June", Demand = 10 }
};
var vPeriods = new[] {
new { Priority = 1, Month = "January" },
new { Priority = 2, Month = "February" },
new { Priority = 3, Month = "March" },
new { Priority = 4, Month = "April" },
new { Priority = 5, Month = "May" },
new { Priority = 6, Month = "June" }
};
var vAll = from p in vProducts
from t in vPeriods
select new
{
Product = p.Product,
Location = p.Location,
Period = t.Priority,
PeriodName = t.Month,
Demand = p.Demand
};
This above query will create all combinations of Products & Period. But, I need to get a list of all products along with the ones that do not have matching Month as shown below.
example
Product Location Priority Month Demand
A Y 1 January 50
A Y 2 February 100
A Y 3 March 20
A Y 4 April null
A Y 5 May null
A Y 6 June 10
Thanks for any comments.
You want to do a left outer join, it will go something like:
var res = from period in vPeriods
join product in vProducts on period.Month equals product.Month into bla
from p in bla.DefaultIfEmpty()
select new { period.Month, period.Priority, Product = p == null ? null : p.Product, Demand = p == null ? -1 : p.Demand };
foreach (var a in res)
{
Console.WriteLine(string.Format("{0} {1} {2}", a.Product, a.Month, a.Demand));
}
Of course that products that do not have matching months don't have locations etc. (as you stated in your example)

Resources