查找相关类的列表递归

时间:2016-12-19 17:57:23

标签: c# list recursion graph-traversal

Supose我有一个代表朋友的班级,另一个代表最好的朋友对和一对最好的朋友的列表,并想知道与每个朋友间接相关的每个朋友,如下:

class Friend
{
    string Name;
}

class BestFriends
{
    Friend NameFriend1;
    Friend NameFriend2;
}

List<BestFriends> ListOfBestFriends = new List<BestFriends>();

Supose我拥有BestFriends对,如下所示:

  • 亚当和布莱恩;
  • Brian和Chris;
  • 克里斯和丹尼尔;
  • Eddie和Ian;
  • Brian和John。

我想创建一个方法,返回与一个特定朋友间接相关的所有朋友的列表。例如:如果我想要Brian的所有间接朋友,该方法将返回{Adam,Chris,Daniel,John}。

List<Friend> IndirectFriends (Friend friendToHasItsIndirectFriendsFound, List<BestFriends> bestFriendsPairs)
{
    ...
}

我怎么能这样做?

3 个答案:

答案 0 :(得分:1)

查找图遍历。在您的情况下,您可以向朋友类添加最好的朋友列表,如下所示:

class Friend
{
    string Name;
    List<Friend> bestFriends;
}

然后使用您拥有的BestFriends对为每位朋友填写此列表。

之后,您可以使用广度优先或深度优先搜索来查找所有间接相关的朋友。

答案 1 :(得分:1)

考虑使用基于集合的操作来解决Linq。

根据您提出的数据结构,解决您需要为直接朋友和间接朋友解决的问题。直接朋友有2例。 1,常见的朋友是NameFriend1,另一个是nameFriend2。这两种情况在IndirectFriends方法的最后解决。

对于间接朋友,案例变得更加复杂,因为您需要将直接朋友的结果加入到同一数据集中两次,一个用于直接朋友在第二个列表上的NameFriend1,另一个用于何时&#39 ; s NameFriend2。这就是解决4个案例的原因。

在IndirectFriends方法的最后,我从列表中排除了常见的朋友,只返回不同的结果。

请注意,此代码仅起作用,因为列表中使用了相同的对象brian,也用于比较。如果要使用相同的值实例化新变量,并且希望linq将它们评估为相等,那么您需要在下面实现IComparable接口链接 How to Implement IComparable interface?

[TestMethod]
public void TestMethod1()
{
    List<BestFriends> ListOfBestFriends = new List<BestFriends>();
    var adam = new Friend { Name = "Adam" };
    var brian = new Friend { Name = "Brian" };
    var chris = new Friend { Name = "Chris" };
    var daniel = new Friend { Name = "Daniel" };
    var eddie = new Friend { Name = "Eddie" };
    var ian = new Friend { Name = "Ian" };
    var john = new Friend { Name = "John" };

    ListOfBestFriends.Add(new BestFriends { NameFriend1 = adam, NameFriend2 = brian });
    ListOfBestFriends.Add(new BestFriends { NameFriend1 = brian, NameFriend2 = chris });
    ListOfBestFriends.Add(new BestFriends { NameFriend1 = chris, NameFriend2 = daniel });
    ListOfBestFriends.Add(new BestFriends { NameFriend1 = eddie, NameFriend2 = ian });
    ListOfBestFriends.Add(new BestFriends { NameFriend1 = brian, NameFriend2 = john });

    var result = IndirectFriends(brian, ListOfBestFriends);
}

List<Friend> IndirectFriends(Friend commonFriend, List<BestFriends> bestFriendsPairs)
{
    /* Get inDirect Friends where commonfriend = NameFriend2 */
    /*  First list is joined on Namefriend2 and Namefriend1 */
    var l1 =  (from bfp in bestFriendsPairs
                join bfpR in bestFriendsPairs
                on bfp.NameFriend2 equals bfpR.NameFriend1
                where bfp.NameFriend1 == commonFriend
                select bfpR.NameFriend2).ToList();

    /* Get inDirect Friends where commonfriend= NameFriend2 */
    /*  First list is joined on Namefriend2 and Namefriend2 */
    l1.AddRange(from bfp in bestFriendsPairs
        join bfpR in bestFriendsPairs
            on bfp.NameFriend2 equals bfpR.NameFriend2
        where bfp.NameFriend1 == commonFriend
        select bfpR.NameFriend1);

    /* Get InDirect Friends where commonfriend = NameFriend2 */
    /*  First list is joined on Namefriend1 and Namefriend2 */
    l1.AddRange (from bfp in bestFriendsPairs
              join bfpL in bestFriendsPairs
              on bfp.NameFriend1 equals bfpL.NameFriend2
              where bfp.NameFriend2 == commonFriend
              select bfpL.NameFriend1);

    /* Get InDirect Friends where commonfriend= NameFriend2 */
    /*  First list is joined on Namefriend1 and Namefriend1 */
    l1.AddRange(from bfp in bestFriendsPairs
                join bfpL in bestFriendsPairs
                on bfp.NameFriend1 equals bfpL.NameFriend1
                where bfp.NameFriend2 == commonFriend
                select bfpL.NameFriend2);

    /* Get Direct Friends where commonfriend= NameFriend2 */
    l1.AddRange(from bfp in bestFriendsPairs
                where bfp.NameFriend2 == commonFriend
                select bfp.NameFriend1);

    /* Get Direct Friends where commonfriend= NameFriend1 */
    l1.AddRange(from bfp in bestFriendsPairs
                where bfp.NameFriend1 == commonFriend
                select bfp.NameFriend2);

    /*exclude commonfriend, and get distinct */
    return l1.Where(f=>f!= commonFriend).Distinct().ToList();
}

答案 2 :(得分:0)

    BestFriends.Where(
    b=>b.NameFriend1.Name!=friend.Name &&
    b.NameFriend2.Name!=friend.Name && 
   BestFriends.Any(b2=>b2.NameFriend1.Name==friend.Name||b2.NameFriend2.Name==friend.Name));

还可以考虑将一个Id添加到Friend类,并使用它来比较名称