2011-03-10 95 views
12

我有几个字段由特定的字符分隔,像这样的字符串:C#:分割字符串和分配结果到多个字符串变量

A,B,C

我想在逗号处分割字符串并将每个结果字段分配给它自己的字符串变量。在Perl我能做到这一点优雅是这样的:

my ($varA, $varB, $varC) = split (/,/, $string); 

什么是实现在C#中相同的结果最简单,最优雅的方式?

我知道我可以分成数组:

string[] results = string.Split(','); 

但我将不得不通过它们的索引,例如访问该字段结果[2]。这很难阅读和容易出错 - 考虑不要有3个30个字段。出于这个原因,我更喜欢每个字段的值在它自己的命名变量中。

+3

不是一个关于如何用C#做的答案,但是F#可以完成你想做的事情:'let [|一个; b; c |] =“1,2,3”.Split(',')' – 2011-03-10 23:31:18

+2

F#很棒。我希望它在商业环境中更受欢迎。 – 2011-03-11 02:02:49

回答

8

我同意。在一个适配器类隐藏拆分似乎是一个很好的做法,并传达你的意图相当好:

public class MySplitter 
{ 
    public MySplitter(string split) 
    { 
     var results = string.Split(','); 
     NamedPartA = results[0]; 
     NamedpartB = results[1]; 
    } 

    public string NamedPartA { get; private set; } 
    public string NamedPartB { get; private set; } 
} 
+0

为什么不使用Tuple? – Linkgoron 2011-03-10 21:40:13

+1

如果我正确理解你的答案,它需要一个类每个使用场景的分裂,因为结果的数量是固定的,以及名称。我希望名称灵活。 – 2011-03-10 21:43:56

+0

我会说它需要每个类型的一个实例,你想有名字。这是一小部分代码,使消费者代码更易于阅读和理解。 – 2011-03-10 21:48:57

0

有没有内置的方式在C#中做的一样,你可以在Perl多分配;然而,有多种解决方案可以通过正常路径将数据导入每个变量。

+0

那么,什么是最优雅的方式来获取数据到每个变量? – 2011-03-10 21:46:44

+0

在我看来,丰富的梅尔顿(上)发布了很好的解决方案 - 它抽象的“废话”(分裂)的后面一个复杂的对象,然后命名造成输出变量到性能。 – Tejs 2011-03-10 21:48:50

1

我推荐一本字典。

List<string> names = new List<string>(){"varA","varB","varC"}; 
Dictionary<string, string> map = new Dictionary<string, string>(); 
string[] results = myLongString.Split(','); 
for (int i = 0; i < results.Length; i++) map.Add(names[i], results[i]); 
+0

这对我来说看起来过于矫枉过正,不太容易阅读(5行而不是1)。 – 2011-03-10 21:45:43

7

您可以使用元组(在.Net 4中添加)。 Tuples in MSDN

此:

public class MySplitter 
{ 
    public MySplitter(string split) 
    { 
     var results = split.Split(','); 
     NamedPartA = results[0]; 
     NamedpartB = results[1]; 
    } 

    public string NamedPartA { get; private set; } 
    public string NamedPartB { get; private set; } 
} 

可以用的东西来实现这样的:

public Tuple<string,string> SplitIntoVars(string toSplit) 
{ 
    string[] split = toSplit.Split(','); 
    return Tuple.Create(split[0],split[1]); 
} 

有了一个元组,你可以使用:

var x = SplitIntoVars(arr); 
// you can access the items like this: x.Item1 or x.Item2 (and x.Item3 etc.) 

您还可以创建一个元组使用Tuple<string,int>等。

另外...我真的不喜欢输出参数,所以你模仿使用 Tuple(显然,也是不同类型)返回多个值。 这样的:

public void SplitIntoVariables(string input, out a, out b, out c) 
{ 
    string pieces[] = input.Split(','); 
    a = pieces[0]; 
    b = pieces[1]; 
    c = pieces[2]; 
} 

变成这样:

public Tuple<string,string,string> SplitIntoVariables(string[] input) 
    { 
     string pieces[] = input.Split(','); 
     return Tuple.Create(pieces[0],pieces[1],pieces[2]); 
    } 

其他(更有想象力的)的选项,可以创建一个拥有自己的价值(以ViewBag一个类似于在ASP.NET MVC)的ExpandoObject(动态)

+1

有趣。之前不知道元组。 – 2011-03-10 22:09:01

+0

不提示元组的原因之一是结果[0]不比tuple.Item1,Item2等清晰得多。OP显式声明了对命名值的渴望。 – 2011-03-11 02:01:52

+0

我认为它比数组更好,因为它并不完全使用索引,并且不会重新创建FW中存在的结构。无论哪种方式,我认为最好的解决方案可能会涉及一个更接近实际问题的解决方案,而不是像当前问题那么普遍。国际海事组织最优雅的解决方案(如果你不能创建一个好的具体类)将是像动态词典(如ViewBag)的东西。 – Linkgoron 2011-03-11 02:13:06

3

谁又无法抗拒Linq的疯狂!

string names = "Joe,Bob,Lucy"; 
var myVars = names.Split(',').Select((x, index) => Tuple.Create(index,x)).ToDictionary(x => "var" + x.Item1, y => y.Item2); 
Debug.WriteLine(myVars["var0"]); 
+1

Sooo ...你有一个字符串[var +索引]的字符串,而不是一个字符串数组[索引]? – Linkgoron 2011-03-10 23:30:09

+3

那是疯了... – gt124 2011-03-10 23:48:05

2

不是单线解决方案。但是,如何使用附加out参数的扩展方法?

public static IEnumerable<T> Unpack<T>(this IEnumerable<T> source, out T target) 
{ 
    target = source.First(); 
    return source.Skip(1); 
} 

然后,你可以使用这样的方法。

string values = "aaa,bbb,ccc"; 
string x, y, z; 
values.Split(',') 
    .Unpack(out x) 
    .Unpack(out y) 
    .Unpack(out z); 

请注意,Unpack方法枚举了两次序列。所以,只有当IEnumerable对象中的数据可重复时,我才会使用它。

我也没在意,因为我认为,通常我们不会拆开一个大阵检查方法的性能。

当然,你可以使用ref改性剂代替out,并且使用会有所不同。

0

我无法抗拒增添了滑稽:)请不要使用本“解决方案”,至少不会原样。

static class StringExtensions 
{ 
    private static readonly Func<object, string, Action<object, object>> GetSetter = 
     (o1, n) => (o2, v) => o1.GetType().GetProperty(n).SetValue(o2, v, null); 

    public static T AssignFromCSV<T>(this string csv, T obj, string[] propertyNames) 
    { 
     var a = csv.Split(new[] {','}); 
     for (var i = 0 ; i < propertyNames.Length; i++) 
     { 
      GetSetter(obj, propertyNames[i])(obj, a[i]); 
     } 
     return obj ; 
    } 
} 

class TargetClass 
{ 
    public string A { get; set; } 

    public string B { get; set; } 

    public string C { get; set; } 
} 

用法:

var target = "1,2,3".AssignFromCSV(new TargetClass(), new[] {"A", "B", "C"}) ; 
1

@pnvn具有与解压模式一个伟大的想法,但它可以提高到迭代在单次枚举,提供默认过去枚举结束并以可预测的方式处理任何类型或大小的枚举。

下面是使用C# 7 out variables feature一个例子。

"A,B,C".Split(',') 
    .Unpack(out string varA) 
    .Unpack(out string varB); 

这需要两个扩展方法,一个用于IEnumerable的开始,所述第二对的IEnumerator对于每个后续呼叫。

public static IEnumerator<T> Unpack<T>(this IEnumerable<T> source, out T item) 
{ 
    var enumerator = source.GetEnumerator(); 
    if (enumerator.MoveNext()) 
    { 
     item = enumerator.Current; 
     return enumerator; 
    } 
    item = default(T); 
    return null; 
} 

public static IEnumerator<T> Unpack<T>(this IEnumerator<T> enumerator, out T item) 
{ 
    if (enumerator != null && enumerator.MoveNext()) 
    { 
     item = enumerator.Current; 
     return enumerator; 
    }    
    item = default(T); 
    return null; 
}