【问题标题】:Find a list of related classes Recursively递归查找相关类的列表
【发布时间】:2016-12-19 17:57:23
【问题描述】:

假设我有一个类代表一个朋友,另一个类代表最好的朋友对和最好的朋友对的列表,并且想知道与每个人的最好朋友间接相关的每个朋友,如下所示:

class Friend
{
    string Name;
}

class BestFriends
{
    Friend NameFriend1;
    Friend NameFriend2;
}

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

假设我有如下 BestFriends 对:

  • 亚当和布赖恩;
  • 布赖恩和克里斯;
  • 克里斯和丹尼尔;
  • 埃迪和伊恩;
  • 布赖恩和约翰。

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

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

我该怎么做?

【问题讨论】:

  • 您的措辞具有误导性。您不是在搜索相关类,而是在搜索同一类的相关对象(在您的情况下为 Friend)。鉴于此,我不明白您的 IndirectFriends 方法中第一个参数的含义。我猜是你想要间接朋友的Friend?你如何定义“间接朋友”?您的递归有任何深度,还是仅从朋友最好的朋友开始的第一级才能找到间接关系?请澄清。提示:阅读图表。
  • 我认为您实际上需要一个图遍历算法,这可能超出了 Stack Overflow 答案的范围。
  • @K.Berger Friend 参数是我要查找所有间接相关朋友的朋友。 “间接朋友”是指可以间接连接到Friend参数的所有级别的所有朋友(查看我的示例)。我想我应该使用graph transversal,但我以前从未使用过。

标签: c# list recursion graph-traversal


【解决方案1】:

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

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

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

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

【讨论】:

  • 是的,我想我必须使用图形横向。谢谢!由于其他原因,我无法将最好的朋友列表添加到我的 Friend 班级。
  • 如果你不能改变班级,你可以创建一个字典,为每个朋友保存最好的朋友列表:Dictionary&lt;Friend, List&lt;Friend&gt;&gt;
【解决方案2】:

考虑使用基于集合的操作通过 Linq 解决这个问题。

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

对于间接朋友,情况会变得更加复杂,因为您需要将直接朋友的结果加入同一数据集两次,一次是直接朋友是第二个列表中的 NameFriend1,另一次是当它是 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();
}

【讨论】:

    【解决方案3】:
        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));
    

    还可以考虑向 Friend 类添加一个 Id 并使用它来比较而不是名称

    【讨论】:

    • 这只深入一层;如果他想要更多,你需要真正的图遍历。
    猜你喜欢
    • 2019-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-03
    • 2020-11-28
    • 2020-11-03
    • 2015-05-03
    相关资源
    最近更新 更多