我有这个字符串:
string input = "1,2,3,4,s,6";
注意s
字符。
我只想使用LINQ在List<int>
中转换此字符串。我最初以这种方式尝试过:
var myList = new List<int>();
input.Split(',').ToList().ForEach(n =>
myList.Add(int.TryParse(n, out int num) ? num : -1)
);
lista.RemoveAll(e => e == -1);
但我更喜欢没有-1
而不是无数字符。
所以现在我尝试这个:
var myList = new List<int>();
input.Split(',').ToList()
.FindAll(n => int.TryParse(n, out int _))
.ForEach(num => myList.Add(int.Parse(num)));
我更喜欢这个,但是解析发生两次(首先是TryParse
然后是Parse
)真的很遗憾。但是,根据我的理解,TryParse中的out变量是无用的(或不是?)。
你有其他人建议(使用LINQ)吗?
答案 0 :(得分:2)
public class ParsesStringsToIntsWithLinq
{
public IEnumerable<int> Parse(string input)
{
var i = 0;
return (from segment in input.Split(',')
where int.TryParse(segment, out i)
select i);
}
}
[TestClass]
public class Tests
{
[TestMethod]
public void IgnoresNonIntegers()
{
var input = "1,2,3,4,s,6";
var output = new ParsesStringsToIntsWithLinq().Parse(input);
Assert.IsTrue(output.SequenceEqual(new []{1,2,3,4,6}));
}
}
它不会返回List<int>
,但我必须在某处画线。你可以列出一个清单。
答案 1 :(得分:1)
使用一个很好的扩展方法
public static IEnumerable<T> AsSingleton<T>(this T source) {
yield return source;
}
(如果愿意,可以用new[] { n }
替换)
input.Split(',').SelectMany(s => Int32.TryParse(s, out var n) ? n.AsSingleton() : Enumerable.Empty<int>()).ToList()
答案 2 :(得分:0)
你可以这样做:
List<int> numbers = input
.Split(',')
.Where(t => int.TryParse(t, out int a))
.Select(int.Parse)
.ToList();
答案 3 :(得分:0)
我更喜欢做一个好帮手功能:
Func<string, int?> tryParse = s => int.TryParse(s, out int n) ? (int?)n : null;
然后解决这个问题很简单:
string input = "1,2,3,4,s,6";
List<int> myList =
input
.Split(',')
.Select(s => tryParse(s))
.Where(n => n.HasValue)
.Select(n => n.Value)
.ToList();
这给出了:
1 2 3 4 6
答案 4 :(得分:0)
int i = 0;
var myList = (from s in input.Split(',') where int.TryParse(s, out i) select i).ToList();
如果数字始终是单个ASCII数字:
var myList = "1,2,3,4,s,6".Select(c => c ^ 48).Where(i => i < 10).ToList();
RegEx替代方案很少有趣:
var myList2 = Regex.Split("1,2,3,4,s,6", "[^0-9]+").Select(int.Parse).ToList(); // if the string starts and ends with digits
var myList3 = Regex.Replace("1,2,3,4,s,6", "[^0-9]+", " ").Trim().Split(' ').Select(int.Parse).ToList();
var myList4 = Regex.Matches("1,2,3,4,s,6", "[0-9]+").Cast<Match>().Select(m => int.Parse(m.Value)).ToList();
答案 5 :(得分:0)
为什么必须是LINQ?
尝试:
//Come up a better name...
public static List<int> ConvertToIntListNoLinq(string input)
{
List<int> output = new List<int>();
foreach(string s in input.Split(','))
{
if(int.TryParse(s, out int result))
{
output.Add(result);
}
}
return output;
}
答案 6 :(得分:0)
这是一个通用的LINQ扩展,它使用cap_ios.h
。这将允许您传入一个返回delegate
的函数,同时“保留”bool
变量的结果(如out
)。
用法:
int.TryParse
代码:
string input = "1,2,3,4,s,6";
List<int> myList = input.Split(',').SelectTry<string, int>(int.TryParse).ToList();
答案 7 :(得分:0)
我认为这也是一种干净的方法。即使它使用了额外的变量,我们获得的好处是它干净且易于理解。
string ids = "2,4,2,4,5,s"
const int inValidInt = -99;
var ids = ids.Split(',')
.Select(id =>
{
int parsedId = int.TryParse(id, out parsedId) ? parsedId : inValidInt;
return parsedId;
})
.Where(x => x != inValidInt).ToList();
答案 8 :(得分:-1)
.Split(...).ToList()
,因为String[]
已经可以枚举。FindAll
,ForEach
和RemoveAll
方法不是Linq方法,它们是List<T>
的成员。他们的Linq等价物为Where
。像这样:
List<Int32> numbers = "1,2,3,4,s,6"
.Split(',')
.Select( s => { Int32 val; return Int32.TryParse( s, NumberStyles.Integer, CultureInfo.InvariantCulture, out val ) ? val : -1 } )
.Where( n => n != -1 )
.ToList();
您可以使用辅助方法使其更简洁:
static Int32 Parse(String s) {
Int32 ret;
if( Int32.TryParse( s, NumberStyles.Integer, CultureInfo.InvariantCulture, out ret ) ) {
return ret;
}
return -1;
}
变为:
List<Int32> numbers = "1,2,3,4,s,6"
.Split(',')
.Select( s => Parse( s ) )
.Where( n => n != -1 )
.ToList();
如果您不想保留-1
,则可以使用可为空的整数:
static Int32? Parse(String s) {
Int32 ret;
if( Int32.TryParse( s, NumberStyles.Integer, CultureInfo.InvariantCulture, out ret ) ) {
return ret;
}
return null;
}
List<Int32> numbers = "1,2,3,4,s,6"
.Split(',') // String to String[]
.Select( s => Parse( s ) ) // String[] to IEnumerable<Int32?>
.Where( n => n != null ) // filter out nulls
.Select( n => n.Value ) // IEnumerable<Int32?> to IEnumerable<Int32>
.ToList(); // IEnumerable<Int32> to List<Int32>