C# 从json数组连接自定义对象的字符串属性
下面是问题的简要说明。 从服务器上我得到了json数组,它看起来类似于:C# 从json数组连接自定义对象的字符串属性,c#,json,linq,C#,Json,Linq,下面是问题的简要说明。 从服务器上我得到了json数组,它看起来类似于: [ { "messagenumber": "0529069f-a403-4eea-a955-430a10995745", "message": "A", "partnumber": 1, "total": 3 }, { "messagenumber": "0529069f-a403-4eea-a955-430a10995745", "message": "
[
{
"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
}......
]
它表示消息部分的列表。属于同一组的消息部分被赋予相同的messagenumber,并且partnumber表示订单号。在客户端上,我必须在最后合并属于同一组的所有消息部分,并呈现完整的消息。从上面的示例中,对于单个消息,结果如下所示:
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
最终结果应该是FullMessage对象的集合。
此外,应该忽略部分消息(并非所有部分都存在)
是否可以使用LINQ语句优雅地完成此操作
谢谢您的建议。尝试以下代码:
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)
});
var输入=新列表();
var result=input.GroupBy(m=>new{m.MessageNumber,m.Total})
.其中(g=>g.Count()==g.Key.Total)
.选择(g=>newfullmessage
{
MessageNumber=g.Key.MessageNumber,
Message=g.OrderBy(i=>i.PartNumber).Aggregate(“,(c,n)=>c+n.Message)
});
假设消息看起来像
public class FullMessage
{
public string MessageNumber { get; set; }
public string Message { get; set; }
public int PartNumber { get; set; }
public int Total { get; set; }
}
以下是我可能的解决方案的想法:
FullMessage
对象统计总数(不确定是否需要统计,因此这是可选的)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;
}));
IEnumerable combinedMessages=messages.GroupBy(m=>m.MessageNumber)
.Select(g=>g.OrderBy(m=>m.PartNumber)
.Aggregate(new FullMessage(){MessageNumber=g.Key},(r,m)=>
{
r、 消息+=m.消息;
//不确定代码中是否需要计数
//所以下面的行是可选的
r、 总数+=m.总数;
返回r;
}));
下面是一个示例代码:
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;}
}
void Main()
{
//测试模拟数据
var数据=新列表{
新ServerMessagePart{
Messagenumber=“0529069f-a403-4eea-a955-430A1099545”,
Message=“A”,
零件号=1,
总数=3
},
新ServerMessagePart{
Messagenumber=“0529069f-a403-4eea-a955-430A1099545”,
Message=“C”,
零件号=3,
总数=3
},
新ServerMessagePart{
Messagenumber=“0529069f-a403-4eea-a955-430A1099545”,
Message=“B”,
零件号=2,
总数=3
},
新ServerMessagePart{
Messagenumber=“52e7d68d-462b-46b9-8eec-f289bcdf7b06”,
Message=“AA”,
零件号=1,
总数=2
}
};
//编译消息
var messages=新列表();
//Process server部分消息-按消息编号对部分消息进行分组
var partialMessages=data.GroupBy(x=>x.Messagenumber);
foreach(部分消息中的var messageParts){
//获取预期的零件号
预期var=messageParts.Max(x=>x.Total);
//跳过未完成的消息
if(messageParts.Count()<预期值){
继续;
}
//对消息进行排序并编译消息
var message=messageParts.OrderBy(x=>x.Partnumber)。选择(x=>x.message)。聚合((x,y)=>x+y);
//最后信息
添加(新服务器消息){
Messagenumber=messageParts.First().Messagenumber,
消息=消息
});
}
//最后信息
}
类服务器消息{
公共字符串Messagenumber{get;set;}
公共字符串消息{get;set;}
}
类ServerMessagePart{
公共字符串Messagenumber{get;set;}
公共字符串消息{get;set;}
公共整数零件号{get;set;}
公共整数总计{get;set;}
}
这应该满足您的要求:
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));
var myList=new List();
myList.GroupBy(msg=>msg.MessageNumber)
.Where(grouping=>grouping.Count()==grouping.First().Total)
.Select(grouping=>grouping.OrderBy(x=>x.order))
.Select(分组=>grouping.Select(x=>x.Message)
.骨料((x,y)=>x+y));
其作用如下:
MessageNumber
PartNumber
对每个分组的所有消息进行排序,以确保所有消息的顺序正确您可以使用
Aggregate()
是的,his可以通过LINQ轻松完成,但是groupby
是否保证排序保持稳定?似乎您的解决方案忽略了这一要求:“应该忽略部分消息”@JamesCurran不知道,这就是为什么我将其移动到此处唯一缺少的东西:.Select(I=>I.Message):g.OrderBy(i=>i.PartNumber)。选择(i=>i.Message)。聚合(“,(c,n)=>c+n)
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);