从string []中选择整数,并返回int []

时间:2010-08-19 15:39:09

标签: c# linq arrays

我有一个数组string[],其值大部分可转换为整数。

var values = new [] {"", "1", "2", "a", "3"};

我需要将值转换为整数数组,丢弃任何不可转换的项目。所以我最终得到了

var numbers = new [] {1, 2, 3};

最有效(最快捷,干净的代码)方法是什么?

9 个答案:

答案 0 :(得分:4)

var numbers = values.Select(
    s => {
        int n;
        if (!int.TryParse((s ?? string.Empty), out n)) 
        {
            return (int?)null;
        }
        return (int?)n;
    }
)
.Where(n => n != null)
.Select(n => n.Value)
.ToArray();

答案 1 :(得分:4)

这是我对此的看法。它使用单独的方法,但在不使用可空值的情况下干净地表达条件解析:

private static IEnumerable<int> ParseInt32s(IEnumerable<string> value)
{
    foreach(var value in values)
    {
        int n;

        if(Int32.TryParse(value, out n))
        {
            yield return n;
        }
    }
}

用法:

string[] values;

var parsedValues = ParseInt32s(values).ToArray();

答案 2 :(得分:3)

这可以在单个linq语句中完成,而无需进行两次解析:

var numbers = values
    .Select(c => { int i; return int.TryParse(c, out i) ? i : (int?)null; })
    .Where(c => c.HasValue)
    .Select(c => c.Value)
    .ToArray();

答案 3 :(得分:3)

我个人使用的扩展方法与其他人发布的方法略有不同。它专门使用自定义WeakConverter<TSource, TResult>委托来避免Ron's answer在每个对象上调用ToString()的问题,同时保持与Jared's answer不同的通用性(尽管我会承认有时会尝试使一切通用都过度了 - 但在这种情况下,额外的努力实际上并不是我认为在可重用性方面的重大好处。)

public delegate bool WeakConverter<TSource, TResult>(TSource source, out TResult result);

public static IEnumerable<TResult> TryConvertAll<TSource, TResult>(this IEnumerable<TSource> source, WeakConverter<TSource, TResult> converter)
{
    foreach (TSource original in source)
    {
        TResult converted;
        if (converter(original, out converted))
        {
            yield return converted;
        }
    }
}

有了这个,您可以非常简单而强大地将string[]转换为int[](无需双重解析):

string[] strings = new[] { "1", "2", "abc", "3", "", "123" };

int[] ints = strings.TryConvertAll<string, int>(int.TryParse).ToArray();

foreach (int x in ints)
{
    Console.WriteLine(x);
}

输出:

1
2
3
123

答案 4 :(得分:2)

编辑:更新为不使用try / catch,因为StackOverflow用户指出它很慢。

试试这个。

var values = new[] { "", "1", "2", "a", "3" };
List<int> numeric_list = new List();
int num_try = 0;
foreach (string string_value in values)
{
    if (Int32.TryParse(string_value, out num_try) {
        numeric_list.Add(num_try);
    }

    /* BAD PRACTICE (as noted by other StackOverflow users)
    try
    {
        numeric_list.Add(Convert.ToInt32(string_value));
    }
    catch (Exception)
    {
        // Do nothing, since we want to skip.
    }
    */
}

return numeric_list.ToArray();

答案 5 :(得分:1)

您可以尝试以下

public static IEnumerable<int> Convert(this IEnumerable<string> enumerable) {
  Func<string,int?> convertFunc = x => {
    int value ;
    bool ret = Int32.TryParse(x, out value);
    return ret ? (int?)value : null;
  };
  return enumerable
    .Select(convertFunc)
    .Where(x => x.HasValue)
    .Select(x => x.Value);
}

然后可以很容易地将其转换为数组。

var numbers = values.Convert().ToArray();

答案 6 :(得分:1)

有一些简单的LINQ:

var numbers = values.Where(x => { int num = 0; return Int32.TryParse(x, out num); })
                    .Select(num => Int32.Parse(num));

值得注意的是,这会将每个字符串转换两次强制执行此操作会使您失去一些清晰度,但会获得一些速度(作为IEnumerable扩展):

public static IEnumerable<int> TryCastToInt<T>(this IEnumerable<T> values)
  int num = 0;
  foreach (object item in values) {
    if (Int32.TryParse(item.ToString(), num)) {
      yield return num;
    }
  }
}

答案 7 :(得分:0)

int n;
var values = new[] { "", "1", "2", "a", "3" };
var intsonly = values.Where (v=> Int32.TryParse(v, out n)).Select(x => Int32.Parse(x));

答案 8 :(得分:0)

var numbers = values
    .Where(x => !String.IsNullOrEmpty(x))
    .Where(x => x.All(Char.IsDigit))
    .Select(x => Convert.ToInt32(x))
    .ToArray();