C#LINQ仅在父级分层父子关系数据中的父级

时间:2016-03-24 09:52:31

标签: c# linq

我在LINQ中遇到了一个有趣的问题,我不知道如何解决它。这是我的数据的样子

我有一个Send对象列表(List<Send>),其中Send对象具有以下属性

public class Send
{   
    public string messageName { get; set; }
    public string Port { get; set; }        
    public string Type { get; set; }
}

其中Port可以是PortA, PortB等。类型只能是"receive""transmit",而messageName可以是

0_firstmessage
1_secondmessage
2_thirdmessage
  

messageName始终在开头0,1,2 .... N。

处有一个标识符

我当前的列表包含以下数据。数据中需要注意的几点事项

  1. 我的数据已根据Ports排序。所以,PortA数据来了 首先是PortB。
  2. “receive”类型的每条消息后跟0或N个发送消息组。
  3. 每个传输消息始终都有父接收。
  4. 我的数据:

    MESSAGENAME, PORT  , TYPE  
        - 0_message , PortA , receive
           - 1_message , PortA , transmit
           - 3_message , PortA , transmit
           - 7_message , PortA , transmit
        - 8_message , PortA , receive
           - 9_message , PortA , transmit
    
        - 2_message , PortB , receive
        - 4_message , PortB , receive
           - 5_message , PortB , transmit
           - 6_message , PortB , transmit
        - 10_message, PortB , receive
           - 11_message , PortB , transmit
    

    我的最终输出应该是这样的。

     MESSAGENAME, PORT  , TYPE  
    - 0_message , PortA , receive
       - 1_message , PortA , transmit
       - 3_message , PortA , transmit
       - 7_message , PortA , transmit
    - 2_message , PortB , receive
    - 4_message , PortB , receive
       - 5_message , PortB , transmit
       - 6_message , PortB , transmit
    - 8_message , PortA , receive
       - 9_message , PortA , transmit
    - 10_message, PortB , receive
       - 11_message , PortB , transmit
    

    我希望ORDERBY基于MESSAGE_NAME仅收到“接收”类型的消息。孩子“传送”信息应保持不变。

    我在线搜索了很多,但我不知道如何编写这个LINQ查询。

    这是一个例子:你可以在这里玩。 https://dotnetfiddle.net/DKOOk2

4 个答案:

答案 0 :(得分:4)

我有一个解决方案,假设您首先收到receive后跟transmit类型的消息。

int gid=0;
var results = messages.Select(m => new 
                     {                                 // Rank each message 
                        m.Type.Equals("Receive", StringComparison.InvariantCultureIgnoreCase ) ? ++gid: gid, 
                        message=m 
                     })
    .GroupBy(g=>g.groupid) // Group them on Rank
    .OrderBy(g=>int.Parse(g.First().message.messageName.Split('_')[0]))  // apply Sort
    .SelectMany(c=>c.Select(x=>x.message)) // flatten structure .
    .ToList() ; 

检查工作example

答案 1 :(得分:0)

请尝试以下代码。

    public class Send : IComparable<Send>
    {
        public string messageName { get; set; }
        public string Port { get; set; }
        public string Type { get; set; }


        public int CompareTo(Send other)
        {
            int results = 0;
            if (this.messageName != other.messageName)
            {
                results = this.messageName.CompareTo(other.messageName);
            }
            else
            {
                if (this.Port != other.Port)
                {
                    results = this.Port.CompareTo(other.Port);
                }
                else
                {
                    results = this.Type.CompareTo(other.Type);
                }
            }
            return results;
        }
    }

答案 2 :(得分:0)

我希望这个LINQ可以帮到你:

var a = mylist.OrderBy(x => x.MESSAGENAME).Where(y => y.TYPE == "receive")
                      .Concat(mylist.Where(z => z.TYPE!= "receive"));

因此,您将获得IEnumerable,其中第一个按顺序发送按消息类型接收和第二个 - 所有其余发送无序。

答案 3 :(得分:0)

我还有另一个建议。你可以添加一个字典并将你的列表放在哪里键 - 将是你的发送消息类型=“接收”然后你可以简单地按键排序。检查此代码:

        List<Send> messages = new List<Send>();

    messages.Add(new Send() {messageName ="0_message" , Port = "PortA", Type="Receive" });
    messages.Add(new Send() {messageName ="1_message" , Port = "PortA", Type="transmit" });
    messages.Add(new Send() {messageName ="3_message" , Port = "PortA", Type="transmit" });
    messages.Add(new Send() {messageName ="7_message" , Port = "PortA", Type="transmit" });
    messages.Add(new Send() {messageName ="8_message" , Port = "PortA", Type="Receive" });
    messages.Add(new Send() {messageName ="9_message" , Port = "PortA", Type="transmit" });
    messages.Add(new Send() {messageName ="2_message" , Port = "PortB", Type="Receive" });
    messages.Add(new Send() {messageName ="4_message" , Port = "PortB", Type="Receive" });
    messages.Add(new Send() {messageName ="5_message" , Port = "PortB", Type="transmit" });
    messages.Add(new Send() {messageName ="6_message" , Port = "PortB", Type="transmit" });
    messages.Add(new Send() {messageName ="10_message" , Port = "PortB", Type="Receive" });
    messages.Add(new Send() {messageName ="11_message" , Port = "PortB", Type="transmit" });


     Dictionary<Send, List<Send>> myDict = new Dictionary<Send, List<Send>>();
        List<Send> mylist2 = new List<Send>();
        Send messagename = new Send();
        int i = 0;


        foreach (Send s in messages)
        {
            if (s.Type == "Receive" || s.Type == "receive")
            {
                if (i != 0)
                {
                    myDict.Add(messagename, mylist2);
                }
                messagename = s;
                mylist2 = new List<Send>();
            }
            else
            {
                mylist2.Add(s);
            }

            if(i== messages.Count()-1)
            {
                myDict.Add(messagename, mylist2);
            }

            i++;
        }

        var q = myDict.OrderBy(x => int.Parse(x.Key.messageName.Split('_')[0]));

如果需要,可以将字典转换回列表:

        List<Send> newlist = new List<Send>();

        foreach (KeyValuePair<Send, List<Send>> k in q)
        {
            newlist.Add(k.Key);

            foreach (Send s in k.Value)
            {
                newlist.Add(s);
            }
        }