String.split()是否可以返回元组?

时间:2018-03-09 09:45:04

标签: c#

我需要string split()并将其值分配给两个变量。 split()是否可以返回tuple而不是string[],以便我可以执行以下操作:

String myString = "hello=world"
value, id = myString.Split('=');

我正在寻找一些优雅的解决方案。

5 个答案:

答案 0 :(得分:16)

如果你可以使用C#7 - 你可以使用元组解构。如果type具有名为Deconstruct的具有适当签名的静态或扩展方法 - 则可以解构此类型。所以你可以使用这样的扩展方法:

public static class Extensions {
    public static void Deconstruct<T>(this IList<T> list, out T first, out IList<T> rest) {

        first = list.Count > 0 ? list[0] : default(T); // or throw
        rest = list.Skip(1).ToList();
    }

    public static void Deconstruct<T>(this IList<T> list, out T first, out T second, out IList<T> rest) {
        first = list.Count > 0 ? list[0] : default(T); // or throw
        second = list.Count > 1 ? list[1] : default(T); // or throw
        rest = list.Skip(2).ToList();
    }
}

然后您可以使用此语法解构字符串数组(实现IList<string>)(您可能需要添加适当的using以便上面的扩展方法可以访问):

var line = "a=b";
var (first, second, _) = line.Split('=');
Console.WriteLine(first); // "a"
Console.WriteLine(second); // "b"

var line = "a=b";
var (first, (second, _)) = line.Split('=');
Console.WriteLine(first); // "a"
Console.WriteLine(second); // "b"

这与您的需求非常接近。

只有上面的第一个扩展方法(解构为第一个元素和其余元素),你可以解构为任意长度:

var (first, (second, _)) = line.Split('=');
var (first, (second, (third,  _))) = line.Split('=');
var (first, rest) = line.Split('=');
// etc

只有在您需要更方便的语法来解构前2个值(var (first, second, rest)而不是var (first, (second, rest)))时才需要第二个扩展方法

答案 1 :(得分:3)

使用LinQ:

List<Tuple<string, string>> pairs = lines
    .Select(x => 
    {
        string[] s = x.Split('=');
        return Tuple.Create(s[0], s[1]);
    })
    .ToList();

答案 2 :(得分:1)

在C#7中,您可以使用var out和扩展来声明并使用一组扩展方法从数组中分配多个变量:

static class MyExtensions {
    static void Assign<T>(this IList<T> items, out T v) {
        v = items[0];
    }
    static void Assign<T>(this IList<T> items, out T v0, out T v1) {
        v0 = items[0];
        v1 = items[1];
    }
    static void Assign<T>(this IList<T> items, out T v0, out T v1, out T v2) {
        v0 = items[0];
        v1 = items[1];
        v2 = items[2];
    }
    static void Assign<T>(this IList<T> items, out T v0, out T v1, out T v2, out T v3) {
        v0 = items[0];
        v1 = items[1];
        v2 = items[2];
        v3 = items[3];
    }
    ... // And so on
}

此扩展程序允许您将拆分分解为单个变量,而不是元组:

Assign(myString.Split('='), var out value, var out id);

答案 3 :(得分:0)

您可以使用反射动态创建元组,这将为您提供可变数量元素的元组。

尝试下面的代码段,

    static void Main(string[] args)
    {
        var tupple = GetTuple<string>("hello=world".Split('='));
    }

    public static object GetTuple<T>(params T[] values)
    {
        Type genericType = Type.GetType("System.Tuple`" + values.Length);
        Type[] typeArgs = values.Select(_ => typeof(T)).ToArray();
        Type specificType = genericType.MakeGenericType(typeArgs);
        object[] constructorArguments = values.Cast<object>().ToArray();
        return Activator.CreateInstance(specificType, constructorArguments);
    }

答案 4 :(得分:0)

以下是我最终希望能帮到你的事情:

static void Main()
    {
        var a = new List<string> {
           "ID = Value",
           "id=value",
           "id      =    value"
        };

        var values = new List<string>();
        var ids = new List<string>();
        for (int i = 0; i < a.Count; i++)
        {
            (string value, string id) = SplitText(a[i]);
            values.Add(value);
            ids.Add(id);
        }

        Console.WriteLine($"Values -> {string.Join(", ", values)}, ID's -> {string.Join(", ", ids)}");
    }

    private static (string, string) SplitText(string inputText)
    {
        var tokens = inputText.Split(new[] { ' ', '=' }, StringSplitOptions.RemoveEmptyEntries);
        return (tokens[0], tokens[1]);
    }