Linq lambda foreach

Linq lambda foreach

尝试将每个字符串包装在数组中但它不起作用,意味着 foreach 循环,请解释原因

string s = "keepsakes,table runners,outdoor accessories";
List<string> keys = s.Split(',').ToList();
keys.ForEach(x => x = String.Concat("%", x, "%"));
s = String.Join(",", keys);
Console.WriteLine(s); 

需要"%keepsakes%,%table runners%,%outdoor accessories%"

更新: 非常感谢您的建议(都是一样的)

但是有人可以回答为什么这是有效的而不是在以下情况下有效:

对象

    public class MyItems
    {
        public string Item { get; set; }
    }

和函数

        string s = "keepsakes,table runners,outdoor accessories";
        List<MyItems> keys = s.Split(',').ToList().Select(x => new MyItems(){ Item = x }).ToList();
        keys.ForEach(x => x.Item = String.Concat("%", x.Item, "%"));
        s = String.Join(",", keys.Select(x => x.Item).ToList());
        Console.WriteLine(s);

您没有修改 ForEach 中的列表,您只是创建分配给局部变量 x 但随后被丢弃的字符串。您可以使用 for-loop:

for(int i = 0; i < keys.Count; i++)
{
    keys[i] = String.Concat("%", keys[i], "%");
}

为了它的价值,这里是更短的 LINQ 版本,它也规避了核心问题:

s = string.Join(",", s.Split(',').Select(str => "%" + str + "%"));

List<>.ForEach不能用来改变列表的内容。您可以创建一个新列表或使用 for 循环。

keys = keys.Select(x => "%" + x + "%").ToList();

for(int i = 0; i < keys.Count; i++)
{
    keys[i] = "%" + keys[i] + "%";
}

您可以使用 JoinSelect 以及 Format

string s = "keepsakes,table runners,outdoor accessories";

var output = string.Join(",", s.Split(',').Select(x => string.Format("%{0}%", x)));

你可以做得更简单:用 %,%

替换每个逗号
string s = "keepsakes,table runners,outdoor accessories";
string s2 = "%" + s.Replace("," , "%,%") + "%";

正如其他人所指出的,传递给 List.ForEach 的 lambda 没有 return 值。

LINQ 是惰性的,但String.Join 会强制枚举:

var res = String.Join(",", input.Split(',').Select(s => "%" + s + "%"));

ForEach 不会更改您的字符串列表,它只会使用每个字符串执行一个操作。相反,您可以这样做:

string s = "keepsakes,table runners,outdoor accessories";
List<string> keys = s.Split(',').Select(x => String.Concat("%", x, "%")).ToList();
s = String.Join(",", keys);
Console.WriteLine(s);

另一种方法(没有 lambda):

string result = string.Concat("%", s, "%").Replace(",", "%,%");

另一种方法可以使用 Regex 而不是 LINQ:

string s = "keepsakes,table runners,outdoor accessories";
string pattern = "\,+";
string replacement = "%,";

Regex rgx = new Regex(pattern);
string result = string.Format("%{0}%", rgx.Replace(s, replacement));

编辑:

它使用 class 分配字符串的原因是,当您在第一个实例中使用 foreach 时:

keys.ForEach(x => x = String.Concat("%", x, "%"));

x,keys的元素,是一个字符串,是一个按值传递给函数ForEach的引用。以此为例:

var myString = "I'm a string";

Console.WriteLine(myString);

ChangeValue(myString);

Console.WriteLine(myString);

void ChangeValue(string s)
{
    s = "something else";
}

如果您 运行 该代码段,您会看到 myString 不会在方法 ChangeValue 中更改,因为我们正在尝试替换引用。方法 ForEach 也会发生同样的事情,这是您无法在 ForEach.

中更改列表值的主要原因

相反,如果您这样做:

class MyClass{
    public string aString;
 }

void ChangeValue(MyClass s)
{
    s.aString = "something else";
}

 var myClass = new MyClass();
 myClass.aString =  "I'm a string";

 Console.WriteLine(myClass.aString);

 ChangeValue(myClass);

 Console.WriteLine(myClass.aString);

您确认在第二个 Console.WriteLine 中,字段 aString 的值将更改为 "something else"。 Here 很好地解释了引用类型是如何按值传递的