将逗号分隔的整数字符串转换为整数数组

70

我只找到了一种方法来完成相反的操作:从整数列表或数组创建逗号分隔的字符串,但是没有找到如何将像 string str = "1,2,3,4,5"; 这样的输入转换为整数数组或列表的方法。

这是我的实现(受 Eric Lippert 的这篇帖子启发):

    public static IEnumerable<int> StringToIntList(string str)
    {
        if (String.IsNullOrEmpty(str))
        {
            yield break;
        }

        var chunks = str.Split(',').AsEnumerable();

        using (var rator = chunks.GetEnumerator())
        {
            while (rator.MoveNext())
            {
                int i = 0;

                if (Int32.TryParse(rator.Current, out i))
                {
                    yield return i;
                }
                else
                {
                    continue;
                }
            }
        }
    }

你认为这是一个好方法吗?还是有更简单的,甚至是内置的方法吗?

编辑:对不起,如果出现如"1,2,,,3""###, 5,"等无效输入,则该方法需要处理并跳过它们。


你没有使用foreach,使得你的代码变得不必要地复杂。你正在复制的帖子解决的是一个完全不同的问题。 - SLaks
9个回答

86
你应该使用foreach循环,像这样:

public static IEnumerable<int> StringToIntList(string str) {
    if (String.IsNullOrEmpty(str))
        yield break;

    foreach(var s in str.Split(',')) {
        int num;
        if (int.TryParse(s, out num))
            yield return num;
    }
}

请注意,与您最初的帖子一样,这将忽略无法解析的数字。

如果您想在无法解析数字时抛出异常,您可以使用 LINQ 更简单地实现:

return (str ?? "").Split(',').Select<string, int>(int.Parse);

80
如果您不想使用当前的错误处理行为,非常简单:
return text.Split(',').Select(x => int.Parse(x));

否则,我会使用一个额外的辅助方法(如今早上所见!)
public static int? TryParseInt32(string text)
{
    int value;
    return int.TryParse(text, out value) ? value : (int?) null;
}

并且:

return text.Split(',').Select<string, int?>(TryParseInt32)
                      .Where(x => x.HasValue)
                      .Select(x => x.Value);

或者,如果您不想使用方法组转换:

return text.Split(',').Select(t => t.TryParseInt32(t)
                      .Where(x => x.HasValue)
                      .Select(x => x.Value);

或者以查询表达式形式:
return from t in text.Split(',')
       select TryParseInt32(t) into x
       where x.HasValue
       select x.Value;

5
有些人可能更喜欢具有更好类型推断的λ,我喜欢提供选择 :) - Jon Skeet
关于你提到的第四个代码块,这不是更简单吗?.Split(',').Where(t => !string.IsNullOrEmpty(t)).Select(t => int.Parse(t)).ToArray() - Rafael Herscovici
1
作为一种快捷方式,您可以使用 Select(int.Parse) - The Muffin Man
@Nick:是的,尽管方法组转换在C# 3和C# 4之间略有变化。这可能是一个例子,在C# 3中它不起作用,但在C# 4+中起作用...我总是记不清确切的细节。 - Jon Skeet
1
@BimalDas:是的,因为否则结果将是IEnumerable<int?>而不是IEnumerable<int> - Jon Skeet
显示剩余8条评论

35

不使用lambda函数,并且仅对有效输入进行操作,我认为更清晰的做法是:

Array.ConvertAll<string, int>(value.Split(','), Convert.ToInt32);

3
我发现我不需要这部分 <string, int> - Valamas

7

假设您将从控制台读取字符串。导入System.Linq并尝试以下代码:

int[] input = Console.ReadLine()
            .Split(',', StringSplitOptions.RemoveEmptyEntries)
            .Select(int.Parse)
            .ToArray();

7

这个问题以前已经被问过了。.Net内置了ConvertAll函数,用于在不同类型的数组之间进行转换。您可以将其与Split组合使用,将字符串分隔成字符串数组。

示例函数:

 static int[] ToIntArray(this string value, char separator)
 {
     return Array.ConvertAll(value.Split(separator), s=>int.Parse(s));
 }

Taken from here


7

--编辑-- 看起来我过于字面理解他的问题标题了 - 他是在问一个整数数组而不是List --编辑结束--

又是一个辅助方法...

private static int[] StringToIntArray(string myNumbers)
{
    List<int> myIntegers = new List<int>();
    Array.ForEach(myNumbers.Split(",".ToCharArray()), s =>
    {
        int currentInt;
        if (Int32.TryParse(s, out currentInt))
            myIntegers.Add(currentInt);
    });
    return myIntegers.ToArray();
}

为IT而设计的快速测试代码...

static void Main(string[] args)
{
    string myNumbers = "1,2,3,4,5";
    int[] myArray = StringToIntArray(myNumbers);
    Console.WriteLine(myArray.Sum().ToString()); // sum is 15.

    myNumbers = "1,2,3,4,5,6,bad";
    myArray = StringToIntArray(myNumbers);
    Console.WriteLine(myArray.Sum().ToString()); // sum is 21

    Console.ReadLine();
}

2
这是针对长整型的,但你可以很容易地修改它以适用于整型。
private static long[] ConvertStringArrayToLongArray(string str)
{
    return str.Split(",".ToCharArray()).Select(x => long.Parse(x.ToString())).ToArray();
}

这将在无法解析的数字上抛出异常;他似乎想跳过它们。 - SLaks
这并不是做同样的事情。他的版本通过跳过非整数来优雅地处理它们。 - mqp
好观点,但我是根据他提供的输入示例来进行的: string str = "1,2,3,4,5" - dcp
这样做根本行不通;您忘记调用Split。 这将枚举字符串中的每个字符,并在遇到,时抛出异常。 - SLaks
哦,你是对的。抱歉,我已经纠正了它。但这仅适用于有效的输入。 - dcp

1

我不明白为什么显式地去除枚举器会给您带来任何优势,与使用 foreach 相比没有任何优点。而且,在 chunks 上调用 AsEnumerable 也是没有必要的。


-4
import java.util.*;
import java.io.*;
public class problem
{
public static void main(String args[])enter code here
{
  String line;
  String[] lineVector;
  int n,m,i,j;
  Scanner sc = new Scanner(System.in);
  line = sc.nextLine();
  lineVector = line.split(",");
  //enter the size of the array
  n=Integer.parseInt(lineVector[0]);
  m=Integer.parseInt(lineVector[1]);
  int arr[][]= new int[n][m];
  //enter the array here
  System.out.println("Enter the array:");
  for(i=0;i<n;i++)
  {
  line = sc.nextLine();
  lineVector = line.split(",");
  for(j=0;j<m;j++)
  {
  arr[i][j] = Integer.parseInt(lineVector[j]);
  }
  }
  sc.close();
}
}

在第一行输入数组的大小,用逗号分隔。然后用逗号分隔输入数组的值。结果将存储在数组arr中。 例如: 输入: 2,3 1,2,3 2,4,6 将存储为: arr = {{1,2,3},{2,4,6}};


这是Java。问题是关于C#的。 - OneCricketeer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接