使用LINQ从字符串列表中提取int

本文关键字:提取 int 列表 字符串 LINQ 使用 | 更新日期: 2023-09-27 18:20:34

我有一个List<string>,其中一些字符串是数字。我想把这个子集提取到一个List<int>中。

我已经用一种非常冗长的方式完成了这项工作,如下所示,但我觉得必须有一种更整洁的LINQ方式来构建它。有什么想法吗?

List<string> myStrs = someListFromSomewhere;
List<int> myInts = new List<int>();
foreach (string myStr in myStrs)
{
    int outInt;
    if (int.TryParse(myStr, out outInt))
    {
        myInts.Add(outInt);
    }
}

显然,我不需要解决这个问题——这主要是为了我的LINQ教育。

使用LINQ从字符串列表中提取int

你可以这样做:

int parsed = 0;
myInts = myStrs.Where(x => int.TryParse(x, out parsed)).Select(x => parsed);

这是因为LINQ运算符的执行被推迟,这意味着:
对于myStrs中的每个项目,首先执行Where中的代码并将结果写入parsed。如果TryParse返回true,则执行Select中的代码。在为下一个项目运行整个代码之前,先运行一个项目的整个代码。

LINQ和out参数不能很好地混合。你可以这样做:

var myInts = myStrs
    .Select(s =>
    {
        int outInt;
        return int.TryParse(s, out outInt) ? (int?)outInt : null;
    })
    .Where(i => i.HasValue)
    .Select(i => i.Value)
    .ToList();

因为这是为了LINQ教育。。。如果您真的在寻找如何只使用LINQ语法来实现这一点,那么另一个选项是将解析逻辑移动到一个封装结果和值的类中。

var myInts = from val in myStrs
             let parserVal = new Parser(val)
             where parserVal.IsInt
             select parserVal.Val;

Parser是这样的。。。

class Parser
{
        public bool IsInt { get; set; }
        public int Val { get; set; }
        public Parser(string val)
        {
            int outVal;
            IsInt = int.TryParse(val, out outVal);
            if (IsInt)
            {
                Val = outVal;
            }
        }
}

选择distinct,然后分析每个选择的项目

List<int> myInts = new List<int>();
myInts = myStrs.Distinct().Select(
    x =>
    {
        int parsed;
        int.TryParse(x, out parsed);
        return parsed;
    })  
.ToList();