从字符串列表创建字符串的嵌套列表(数组)

时间:2019-02-13 17:52:57

标签: c# arrays .net string list

我有一个名字列表。通过这些,我想创建一个新的列表列表(或锯齿状数组,如果效果更好),其中较低级别的列表包含名称的变体。

基本思想是,您取一个名字并一次删除一个字母,以创建一个包含所有这些作品以及原始名称的列表。例如,如果您的名字是“ bob”和“ alice”,我想输出

[["bo", "bb","ob","bob"], ["alic", "alie", "alce", "aice", "lice", "alice"]].

我只用一个名字就可以轻松地做到这一点,但是当我尝试创建这样的嵌套列表时遇到了无法解决的问题(我对C#还是比较陌生的)。这是我一直在尝试的玩具示例:

List<string> names = new List<string>()
{
    "alice",
    "bob",
    "curt"
};

//initialize jagged array
string[][] modifiedNames = new string[names.Count][];

        //iterate over all names in "names" list
        foreach(string name in names)
        {
            int nameIndex = names.IndexOf(name);

            //initialize lower level of array
            modifiedNames[nameIndex] = new string[name.Length];

            //create variations of a given name
            for (int i = 0; i < name.Length; i++)
            {
                string newName = name.Substring(0, i) + name.Substring(i + 1);

                if (modNames[nameIndex].Contains(newName) == false)
                    modNames[nameIndex].Add(newName);
            }
            modName.Add(name);

        }

我已经尝试了几种版本,包括列表和数组,但无济于事。在这种情况下,我收到的错误消息是

  

'string []'不包含'Add'的定义,并且找不到可访问的扩展方法'Add'接受类型为'string []'的第一个参数(是否缺少using指令或程序集引用? ?)

非常感谢您的帮助!

5 个答案:

答案 0 :(得分:0)

在使用方法时如何使用列表列表(字符串),然后在返回之前将其转换为数组数组呢?如果返回类型不是一成不变的,甚至可以返回列表列表?

这是一个建议:

    var names = new List<string>()
    {
        "alice",
        "bob",
        "curt"
    };

    var nameVariations = new List<List<string>>();
    foreach (var name in names)
    {
        var variationsOfName = new List<string>();
        for (int i = 0; i < name.Length; i++)
        {
            var newName = name.Substring(0, i) + name.Substring(i + 1);

            if (!variationsOfName.Contains(newName))
            {
                variationsOfName.Add(newName);
            }
        }

        nameVariations.Add(variationsOfName);
    }

    return nameVariations.Select(variationsOfName => variationsOfName.ToArray()).ToArray();

注意:要进行编译,您需要添加Linq(使用System.Linq;)。

答案 1 :(得分:0)

首先,该错误告诉您数组没有Add()函数。正如JohnB所指出的,List可能更适合这里。

第二,我还是不喜欢string[][]。我将使用IDictionary<string, IList<string>>,将您的原始名称存储为键,并将修改后的名称存储为值。这样,原始版本和修改后的版本将存储在一起,而您无需将namesmodifiedNames交叉引用(其中一个是List,另一个(当前)是数组)

IDictionary<string, IList<string>> names = new Dictionary<string, IList<string>>();

names.Add("alice", new List<string>());
names.Add("bob", new List<string>());
names.Add("curt", new List<string>());

foreach (KeyValuePair<string, IList<string>> name in names)
{
    for (int i = 0; i < name.Key.Length; i++)
    {
        string newName = name.Key.Substring(0, i) + name.Key.Substring(i + 1);

        if (!name.Value.Contains(newName))
        {
            name.Value.Add(newName);
        }
    }
}

希望这会有所帮助。

答案 2 :(得分:0)

我将分两步执行此操作。首先,编写一个简单的方法,该方法将获取单个名称的名称变体列表。我们可以使用某些System.Linq扩展方法(例如Select()ToList())来简化代码。下面的Select语句将字符串视为一个字符数组,并且对于索引为t的每个字符i,从name直到该字符之间选择子字符串,并添加该字符之后的name的子字符串,返回一个IEnumerable<string>,我们从中创建一个新的List<string>。然后,我们最终将原始name添加到列表中并返回:

public static List<string> GetNameVariations(string name)
{
    var results = name.Select((t, i) =>
        name.Substring(0, i) + name.Substring(i + 1, name.Length - (i + 1)))
        .ToList();

    results.Add(name);

    return results;
}

然后我们可以使用此方法使用另一种方法从名称列表中获取名称List<List<string>>。在这里,我们为GetNameVariations中的每个名称调用names(每个名称返回一个新的List<string>),并以新的List<List<string>>返回这些列表:

public static List<List<string>> GetNameVariations(List<string> names)
{
    return names.Select(GetNameVariations).ToList();
}

在使用中,这看起来像(使用您的示例):

private static void Main()
{
    var names = new List<string> {"bob", "alice", "curt"};

    foreach (var nameVariations in GetNameVariations(names))
    {
        Console.WriteLine(string.Join(", ", nameVariations));
    }

    GetKeyFromUser("\nDone! Press any key to exit...");
}

输出

![![enter image description here

答案 3 :(得分:0)

通过使用String.Remove(i, 1)一次删除一个字符,并在字符串的长度上遍历i的值,可以简化逻辑。您可以单查询形式编写查询:

var result = names.Select(name => name.Select((_, i) => name.Remove(i, 1)).Reverse().Concat(new[] { name }).ToList()).ToList();

经过重新格式化以提高可读性:

var result = names
    .Select(name => 
        name.Select((_, i) => name.Remove(i, 1))
            .Reverse()
            .Concat(new[] { name })
            .ToList())
    .ToList();

答案 4 :(得分:0)

我认为这是一种相当简单的方法:

List<string> names = new List<string>()
{
    "alice",
    "bob",
    "curt"
};

string[][] modifiedNames =
    names
        .Select(name =>
            Enumerable
                .Range(0, name.Length)
                .Select(x => name.Substring(0, x) + name.Substring(x + 1))
                .Concat(new [] { name })
                .ToArray())
        .ToArray();

给出:

modifiedNames