Reputation: 73
Here is a brief description of the problem. From server I get json array which looks similar to this:
[
{
"messagenumber": "0529069f-a403-4eea-a955-430a10995745",
"message": "A",
"partnumber": 1,
"total": 3
},
{
"messagenumber": "0529069f-a403-4eea-a955-430a10995745",
"message": "B",
"partnumber": 2,
"total": 3
},
{
"messagenumber": "0529069f-a403-4eea-a955-430a10995745",
"message": "C",
"partnumber": 3,
"total": 3
},
{
"messagenumber": "52e7d68d-462b-46b9-8eec-f289bcdf7b06",
"message": "AA",
"partnumber": 1,
"total": 2
}......
]
It represents the list of messages parts. Message parts that belong to the same group are given the same messagenumber, and partnumber represents the order number. On the client I have to, at the end, combine all message parts belonging to the same group and render full message. From example above, result would look like this for individual message:
var msg = new FullMessage();
msg.MessageNumber = "0529069f-a403-4eea-a955-430a10995745";
msg.Message = "ABC"; //here we have full message created out of 3 parts
msg.PartNumber = 1; //not important
msg.Total = 1 //also not important
and the final result should be a collection of FullMessage objects. Also, messages that are partial (not all parts are present) should be ignored.
Can this be done elegantly using LINQ statement(s) ?
Thank you for any suggestion.
Upvotes: 1
Views: 500
Reputation: 7054
Try this code:
var input = new List<FullMessage>();
var result = input.GroupBy(m => new { m.MessageNumber, m.Total })
.Where(g => g.Count() == g.Key.Total)
.Select(g => new FullMessage
{
MessageNumber = g.Key.MessageNumber,
Message = g.OrderBy(i => i.PartNumber).Aggregate("", (c, n) => c + n.Message)
});
Upvotes: 0
Reputation: 8921
This should do what you want:
var myList = new List<FullMessage>();
myList.GroupBy(msg => msg.MessageNumber)
.Where(grouping => grouping.Count() == grouping.First().Total)
.Select(grouping => grouping.OrderBy(x => x.order))
.Select(grouping => grouping.Select(x => x.Message)
.Aggregate((x, y) => x + y));
What this does is the following:
MessageNumber
PartNumber
to ensure everything is in the correct orderThe result is an enumeration of concatenated strings.
Upvotes: 1
Reputation: 103535
Here's mine: (UPDATED to remove partials)
var messages = new Message[] {
new Message("52e7d68d-462b-46b9-8eec-f289bcdf7b06", "BB", 2, 2),
new Message("0529069f-a403-4eea-a955-430a10995745", "A", 1, 3),
new Message("0529069f-a403-4eea-a955-430a10995745", "B", 2, 3),
new Message("0529069f-a403-4eea-a955-430a10995745", "C", 3, 3),
new Message("52e7d68d-462b-46b9-8eec-f289bcdf7b06", "AA", 1, 2),
};
var grouped = (from m in messages
group m by m.messagenumber into g
select new
{
messagenumber = g.Key,
message = String.Join("", g.OrderBy(dr =>dr.partnumber)
.Select(m=>m.message)),
count = g.Count(),
total = g.First().total
}).Where(c=>c.count == c.total);
Upvotes: 0
Reputation: 11399
Let's say the message looks like
public class FullMessage
{
public string MessageNumber { get; set; }
public string Message { get; set; }
public int PartNumber { get; set; }
public int Total { get; set; }
}
Here is the idea of my possible solution:
FullMessage
object using AggregateThe result is this LINQ query:
IEnumerable<FullMessage> combinedMessages = messages.GroupBy(m => m.MessageNumber)
.Select(g => g.OrderBy(m => m.PartNumber)
.Aggregate(new FullMessage() { MessageNumber = g.Key }, (r, m) =>
{
r.Message += m.Message;
//Not sure if counting up is required in your code
//so the following line is optional
r.Total += m.Total;
return r;
}));
Upvotes: 0
Reputation: 5565
An example code below:
void Main()
{
// Testing mocked data
var data = new List<ServerMessagePart> {
new ServerMessagePart{
Messagenumber = "0529069f-a403-4eea-a955-430a10995745",
Message= "A",
Partnumber= 1,
Total = 3
},
new ServerMessagePart{
Messagenumber = "0529069f-a403-4eea-a955-430a10995745",
Message= "C",
Partnumber= 3,
Total = 3
},
new ServerMessagePart{
Messagenumber = "0529069f-a403-4eea-a955-430a10995745",
Message= "B",
Partnumber= 2,
Total = 3
},
new ServerMessagePart{
Messagenumber = "52e7d68d-462b-46b9-8eec-f289bcdf7b06",
Message= "AA",
Partnumber= 1,
Total = 2
}
};
// Compiled messages
var messages = new List<ServerMessage>();
// Process server partial messages - group parsts by message number
var partialMessages = data.GroupBy(x => x.Messagenumber);
foreach(var messageParts in partialMessages) {
// Get expected parts number
var expected = messageParts.Max(x=>x.Total);
// Skip incompleted messages
if(messageParts.Count() < expected) {
continue;
}
// Sort messages and compile the message
var message = messageParts.OrderBy(x => x.Partnumber).Select(x => x.Message).Aggregate((x,y) => x + y);
// Final message
messages.Add(new ServerMessage{
Messagenumber = messageParts.First().Messagenumber,
Message = message
});
}
// Final messages
}
class ServerMessage {
public string Messagenumber {get; set;}
public string Message {get; set;}
}
class ServerMessagePart {
public string Messagenumber {get; set;}
public string Message {get; set;}
public int Partnumber {get; set;}
public int Total {get; set;}
}
Upvotes: 0