如何加入2个列表,其中一个列表包含2个元素?

时间:2013-10-21 00:09:14

标签: c# linq lambda

从我可以告诉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]。我不知道如何实现这一目标。

3 个答案:

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

}

结果:

Result

答案 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();
  }