我在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。
处有一个标识符
我当前的列表包含以下数据。数据中需要注意的几点事项
我的数据:
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
答案 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);
}
}