从我可以告诉LINQ和lambda表达式是解决我的特定问题的方法。在我的办公室,我有一个二维数组[X长度] [2宽度]的IM日志列表,这样我就可以看到谁是谁。但是日志由3位用户ID组成,而不是实际名称。
arrIMLog[x][1]
因此,日志条目可能看起来像这样arrIMLog [0] [0] = 353并且arrIMLog [0] [1] = 563表示用户353 IM用户563.然后,我有一个列表用户ID我想知道他们通过日志搜索他们的IM。
lstSuspects
例如,lstSuspects(1)= 353,lstSuspects(2)= 563等。我想创建一个新的简单列表lstSuspectsContacted,这样我就可以找出lstSuspects上每个人联系过的唯一UserID (#次无关紧要)。我该怎么做?
var lstSuspectsContacted = (from x in arrIMLog
join y in lstSuspects
on arrIMLog[0] or arrIMLog[1] equals lstSuspects // join criteria
select new { arrIMLog[0] or arrIMLog[1]}).ToList();
我遇到的困难是我想要选择数组中的[0]或[1]元素,具体取决于lstSuspects与另一个元素[1]中的arrIMLog之间是否匹配或[0]。我不知道如何实现这一目标。
答案 0 :(得分:1)
这里的解决方案可能看起来更冗长,但更具扩展性和可读性
首先定义日志并怀疑POCO。
public class Log
{
/// <summary>
/// Person initiating the contact
/// </summary>
public int From { get; set; }
/// <summary>
/// Person that was contacted
/// </summary>
public int To { get; set; }
}
public class SuspectConnection
{
public int SuspectId { get; set; }
public List<int> Contacts { get; set; }
}
然后,您可以使用LINQ轻松找到连接。
var suspectConnections = new List<SuspectConnection>();
foreach (var suspect in suspects)
{
var connection = new SuspectConnection() { SuspectId = suspect };
connection.Contacts = logs.Where(x => x.From == suspect || x.To == suspect).Select(x => x.From == suspect ? x.To : x.From).ToList();
suspectConnections.Add(connection);
}
答案 1 :(得分:1)
这是使用lambda连接的快速方法。注意我已经为联系人对中的每个联系人使用了两个联接。 我认为这也是最有效的解决方案。
int[][] log = new int[][] {new int[]{1,2},new int[]{2,1},new int[]{1,3},new int[]{2,3},new int[]{3,4},new int[]{4,1}};
List<Suspect> Suspects = new List<Suspect>(){new Suspect(){SuspectId = 1, Name = "Bob"},new Suspect(){SuspectId = 2, Name = "Frank"},new Suspect(){SuspectId = 3, Name = "Jimmy"},new Suspect(){SuspectId = 4, Name = "DrEvil"}};
//order the contact pairs as 2 --> 1 is the same as 1 --> 2
var q = log.Select (x => x.OrderBy (o => o))
// Put contact record into an object which we have an IComparable for
.Select (s => new Contact(){A = s.ElementAt(0),B= s.ElementAt(1) })
//Now eliminate the duplicates
.Distinct(new ContactComparer())
//get the Name for contact A
.Join(Suspects, contactKey => contactKey.A, suspectKey => suspectKey.SuspectId,(c,s) => new Contact{A = c.A, AName = s.Name, B = c.B})
//get the Name for contact B
.Join(Suspects, contactKey => contactKey.B, suspectKey => suspectKey.SuspectId,(c,s) => new Contact{A = c.A, AName = c.AName, B = c.B, BName = s.Name})
.ToList();
//Classes that were used:
public class Contact
{
public int A { get; set; }
public String AName { get; set; }
public int B { get; set; }
public String BName { get; set; }
}
public class Suspect
{
public int SuspectId { get; set; }
public String Name { get; set; }
}
//We will use this in the .Distinct() linq method, to find the (and remove) the duplicates
public class ContactComparer : IEqualityComparer<Contact>
{
public bool Equals(Contact x, Contact y)
{
//Check whether the compared objects reference the same data.
if (Object.ReferenceEquals(x, y)) return true;
//Check whether any of the compared objects is null.
if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
return false;
//Check whether the id fields are equal.
return x.A == y.A && x.B == y.B;
}
public int GetHashCode(Contact contact)
{
//Check whether the object is null
if (Object.ReferenceEquals(contact, null)) return 0;
//Get hash code for the Name field if it is not null.
long contactA = contact.A == null ? 0 : contact.A;
long contactB = contact.B == null ? 0 : contact.A;
//Calculate the hash code for the product.
return (int)((contactA + contactB) % int.MaxValue);
}
}
结果:
答案 2 :(得分:1)
通过开箱即可解决问题的一种方法,因为我永远不会将其视为LINQ问题。我正在做的是将其重新构建为网络结构。我们只遍历日志一次,如果我们正在查看大型数据集,这可能会成为一个问题。
void ShowCommunication(int[][] communication, int[] suspects)
{
var table = new Dictionary<int, Suspect>();
// We are going through everyone, though
// communication.Where(t => suspects.Contains(t[0]) || suspects.Contains(t[1]))
// could speed it up, although that leaves us with an incomplete graph
foreach (var chat in communication)
{
if (!table.ContainsKey(chat[0])) table[chat[0]] = new Suspect(chat[0]);
if (!table.ContainsKey(chat[1])) table[chat[1]] = new Suspect(chat[1]);
// Remove the if-statement if you want the communication in order
if (!table[chat[0]].CoSuspects.Contains(table[chat[1]]))
{
table[chat[0]].CoSuspects.Add(table[chat[1]]);
table[chat[1]].CoSuspects.Add(table[chat[0]]);
}
}
Console.WriteLine("All members");
foreach (var key in table)
{
Console.WriteLine("{0} talked to {1}", key.Key, string.Join(", ", key.Value.CoSuspects.Select(t => t.ID.ToString())));
}
Console.WriteLine("\nSuspected members");
foreach (var key in table.Where(t => suspects.Contains(t.Key)))
{
Console.WriteLine("{0} talked to {1}", key.Key, string.Join(", ", key.Value.CoSuspects.Select(t => t.ID.ToString())));
}
}
我的助手方法和类:
class Suspect
{
public Suspect(int id)
{
CoSuspects = new HashSet<Suspect>();
this.ID = id;
}
public int ID { get; set; }
public HashSet<Suspect> CoSuspects { get; set; }
}
int[][] GetRandomData()
{
var list = new List<int[]>();
var random = new Random();
for (int i = 0; i < 100; i++)
{
list.Add(new[] { random.Next(10), random.Next(10) });
}
return list.ToArray();
}
int[] GetSuspects()
{
var random = new Random();
var list = new List<int>();
for (int i = 0; i < 3; i++)
{
list.Add(random.Next(10));
}
return list.ToArray();
}