C# 从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": "

下面是问题的简要说明。 从服务器上我得到了json数组,它看起来类似于:

    [
  {
    "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
    对象统计总数(不确定是否需要统计,因此这是可选的)
  • 结果是这个LINQ查询:

    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);