【问题标题】:Concatenate string property of a custom object from json array从 json 数组连接自定义对象的字符串属性
【发布时间】:2017-07-26 18:38:31
【问题描述】:

这里是问题的简要说明。 从服务器我得到 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
  }......
]

它表示消息部分的列表。属于同一组的消息部分被赋予相同的messagenumberpartnumber代表订单号。最后,在客户端上,我必须组合属于同一组的所有消息部分并呈现完整消息。从上面的示例中,单个消息的结果将如下所示:

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 语句优雅地完成吗?

感谢您的任何建议。

【问题讨论】:

  • 你可以使用Aggregate()
  • 是的,他可以通过 Linq 轻松完成

标签: c# json linq


【解决方案1】:

这应该做你想做的:

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

它的作用如下:

  1. 通过MessageNumber 对消息进行分组
  2. 过滤掉所有部分消息
  3. PartNumber 对每个分组的所有消息进行排序,以确保所有消息的顺序正确
  4. 浏览所有分组并选择所有消息
  5. 聚合消息

结果是串联字符串的枚举。

【讨论】:

  • 但是groupby 保证排序保持稳定吗?
  • 您的解决方案似乎忽略了这个要求:“应该忽略部分消息”
  • @JamesCurran 不知道,这就是我移动它的原因
【解决方案2】:

下面的示例代码:

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

【讨论】:

    【解决方案3】:

    假设消息看起来像

    public class FullMessage
    {
        public string MessageNumber { get; set; }
        public string Message { get; set; }
        public int PartNumber { get; set; }
        public int Total { get; set; }
    }
    

    这是我可能的解决方案的想法:

    1. 按消息编号分组
    2. 按部件号对组中的每条消息进行排序
    3. 使用Aggregate 在新的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;
        }));
    

    【讨论】:

      【解决方案4】:

      这是我的:(已更新以删除部分内容)

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

      【讨论】:

        【解决方案5】:

        试试这个代码:

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

        【讨论】:

        • 这里唯一缺少的东西:.Select(i => i.Message): g.OrderBy(i => i.PartNumber).Select(i => i.Message).Aggregate(" ", (c, n) => c + n)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-06-29
        • 1970-01-01
        • 2015-01-19
        • 2012-09-10
        • 1970-01-01
        • 2019-03-04
        相关资源
        最近更新 更多