【问题标题】:Build string through recursive method calls通过递归方法调用构建字符串
【发布时间】:2020-10-04 23:29:18
【问题描述】:

我有以下类结构(简化):

public class MyBaseType
{
    public string InstanceName { get; set; }
    public List<MyBaseType> MyBaseTypeList = new List<MyBaseType>();
    public List<MyObject1> MyObject1List = new List<MyObject1>();
    public List<MyObject2> MyObject2List = new List<MyObject2>();
    // Other properties
}

public class MyObject1
{
    public string SimpleName { get; set; }
    public string Name { get; set; }
    // Other properties
}

public class MyObject2
{
    public string SimpleName { get; set; }
    public string Name { get; set; }
    // Other properties
}

如您所见,MyBaseType 的实例可以包含相同类型的实例列表以及MyObject1MyObject2 的列表。

这对我来说的一个典型用途是呈现如下所示的结构:

MyBaseType instance1
|-> InstanceName = "instance1"
|
|-> MyBaseType instance2
|   |-> InstanceName = "instance2"
|   |
|   |-> MyObject1 object1_1
|   |   |-> SimpleName = "object1_1"
|   |-> MyObject2 object2_1
|   |   |-> SimpleName = "object2_1"
|
|-> MyBaseType instance3
|   |-> InstanceName = "instance3"
|   |
|   |-> MyObject1 object1_2
|   |   |-> SimpleName = "object1_2"
|   |-> MyObject2 object2_2
|   |   |-> SimpleName = "object2_1"
|
|-> MyObject1 object1_3
|   |-> SimpleName = "object1_3"
|-> MyObject2 object2_3
|   |-> SimpleName = "object2_3"

显然,这种结构会变得相当复杂。

然而,我需要做的是递归地深入MyBaseType 列表,跟踪所有InstanceName 值,最后将组合字符串附加到MyObject1MyObject2SimpleName到任一对象的Name 属性。

按照上面的结构示例,名称将是:

MyObject1 object1_1 : instance1_instance2_object1_1
MyObject1 object2_1 : instance1_instance2_object2_1
MyObject1 object1_2 : instance1_instance3_object1_1
MyObject1 object2_2 : instance1_instance3_object1_2
MyObject1 object1_3 : instance1_object1_3
MyObject1 object2_3 : instance1_object2_3

我正在努力寻找一种方法来递归遍历 List&lt;MyBaseType&gt; 并跟踪正在构造的名称。

【问题讨论】:

  • 我很抱歉,虽然你已经经历了相当大的麻烦,以使这有意义。这至少对我来说没有意义。你的最终目标是什么?为什么你需要递归地发生这种情况?总体来说是什么?
  • 递归,因为由于 MyBaseType 的实例可以包含 MyBaseType 实例的列表,因此您必须通过递归到达所述列表为空的实例
  • 嗯,这不需要递归发生。您可以使用for loop 迭代您的列表。此外,如果您想确保设置了基本类型的属性。如果必须,您可以通过构造函数强制其实例化。我认为您对自引用对象的属性有点困惑。就像链表中的节点类。提供的答案只是一个 for 循环,但被隐藏了。您必须阅读 linq 的全部内容。
  • 很有可能你是对的。我会仔细看看。我假设递归,因为我不知道将实例添加到另一个实例的列表多少次。可能是100次
  • 非常感谢!我会调查一下,希望很快有解决方案。

标签: c# .net string recursion nested


【解决方案1】:

试试这样的:

public class MyBaseType
    {
        public string InstanceName { get; set; }
        public List<MyBaseType> MyBaseTypeList = new List<MyBaseType>();
        public List<MyObject1> MyObject1List = new List<MyObject1>();
        public List<MyObject2> MyObject2List = new List<MyObject2>();

        public string GetName()
        {
            return $"{InstanceName}-{string.Join('-',MyBaseTypeList.Select(q => q.GetName()))}";
        }
    }

【讨论】:

  • 我收到“无法从 System.Generic.Collection.IEnumerable 转换为 String”错误...此外,此方法如何设置 MyObject1 和 MyObject2 实例的名称?
  • 设法让它工作,但结果只是特定实例的所有 InstanceName 的串联。没有实例分离,如果你看这个问题,这就是我需要的......
【解决方案2】:

根据 panoskarajohn(我感谢他)和其他所有做出贡献的人提供的 cmets,我提出了以下解决方案,符合我的预期:

public void GenerateNames(string input)
{
    if (!IsEmpty(MyBaseTypeList))
    {
        foreach (MyBaseType mbt in MyBaseTypeList)
        {
            mbt.GenerateNames(input + "_" + mbt.InstanceName);
        }
    }
    else
    {
        foreach (MyObject1 mo1 in MyObject1List)
        {
            mo1.Name = input + "_" + mo1.SimpleName;
        }
        foreach (MyObject2 mo2 in MyObject2List)
        {
            mo2.Name = input + "_" + mo2.SimpleName;
        }
    }
}

【讨论】:

    【解决方案3】:

    您可以尝试在传递基本标识符的地方应用装饰器模式。

    将此方法添加到您的 MyBaseType 类;

    public Dictionary<string,MyObject1> GenerateString(string bString)
        {
            if(bString != null) bString += "_";
    
            Dictionary<string, Object> dict = new Dictionary<string, Object>();
            if (MyBaseTypeList.DefaultIfEmpty() != null)
            {
                 dict = this.MyBaseTypeList.Select(s => s.GenerateString(bString + InstanceName)).SelectMany(d => d).ToDictionary(e => e.Key, e => e.Value);
            }
    
            MyObject1List.ForEach(myObject => dict.Add(bString + InstanceName + "_" + myObject.SimpleName,myObject));
            MyObject2List.ForEach(myObject => dict.Add(bString + InstanceName + "_" + myObject.SimpleName,myObject));
    
            return dict;
        }
    

    这样你就可以得到所有对象的字典,并以它们的路径为键。

    您只需要使用 null 作为参数调用基础对象中的函数。 (实例1)

    【讨论】:

    • 我喜欢这个,我会测试它是否符合我的需要! (请注意,虽然 MyObject1 和 MyObject2 看起来相同,但实际上并非如此。它们的属性与我实际编写的属性不同。我认为我确实指定了这一点)
    • 他们有共同的 SimpleName 吗?如果是这样,您可以将它们包装在仅包含 SimpleName 的类中,这样您就可以保存任何类。
    • 我看到了这个想法,是的,不幸的是,我正在使用的类结构比我在这里的问题中可以显示的更复杂,我无法以任何方式加入这两个类。因此存在冗余,但我知道以后如何排序。
    • 好吧,我们仍然可以使用 2 个完全不同的类,我们可以只使用 Object 作为字典中的包装器,并通过它们各自的标识符来识别每个对象
    • 更改了代码,因此您仍然可以在列表中使用任何对象
    猜你喜欢
    • 2017-10-08
    • 1970-01-01
    • 1970-01-01
    • 2019-06-03
    • 2021-12-28
    • 2014-01-01
    • 2019-12-21
    • 1970-01-01
    • 2023-03-15
    相关资源
    最近更新 更多