我有一个模拟一个人的课程;除了通常的属性之外是该人的手机号码
public class Person
{
// Other properties elided here for brevity's sake
public string PersonMobileNumber { get; set; }
}
向该人发送他们可能会或可能不会回复的短信。我已经定义了一条消息:
public class SmsMessage
{
public string NumberFrom { get; set;}
public string NumberTo { get; set;}
public string MessageContent { get; set; }
public DateTime DateTimeReceived { get; set; }
}
现在我想看到的是谁回复了我的短信。
简单地说,您有许多短信(List<SmsMessage>
)和一些人(List<Person>
)
在旧的LINQ之前的日子里,我只需要foreached
通过两个集合,在第一个集合中有一个foreach
,但我认为LINQ应该能够在这里帮助我。我提出的相关陈述如下:
List<Person> peopleThatResponded =
people.Where(p => smsMessages.Exists(s => s.NumberFrom == p.MobileNumber)).ToList();
只是觉得这对小型数据集很有用(这是基于调试它并观察代码中的循环)但我确信有一种更高效的方法可以做到这一点。 FWIW我可以完全控制类定义,并可以进行任何需要进行的更改。
答案 0 :(得分:2)
更加高效的方式是加入他们:
var peopleThatResponded = from pers in people
join sms in smsMessages
on pers.PersonMobileNumber equals sms.NumberFrom
select pers;
List<Person> peopleListThatResponded = peopleThatResponded.ToList();
Why is LINQ JOIN so much faster than linking with WHERE?
但如果他们多次回复,那会重复人们。另一种方法是使用HashSet<string>
代替更有效的列表。
var smsNumbers = new HashSet<string>(smsMessages.Select(sms => sms.NumberFrom));
List<Person> peopleThatResponded = people
.Where(p => smsNumbers.Contains(p.PersonMobileNumber)).ToList();
答案 1 :(得分:1)
在Exists
中使用where
是一个O(n * m)解决方案,因此随着人数或消息的增加,这将会明显变慢。
您可以将现有数字放在哈希集中,然后将人与之匹配。这将是一个O(n + m)解决方案,所以它可以很好地扩展:
HashSet<string> numbers =
new HashSet<string>(smsMessages.Select(m => m.NumberFrom));
List<Person> peopleThatResponded =
people.Where(p => numbers.Contains(p.MobileNumber)).ToList();