Linq lambda foreach

时间:2015-04-15 12:17:52

标签: c# linq lambda

尝试将每个字符串包装在数组中但它不起作用,意味着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%"

UPD: 非常感谢您的建议(这是一样的)

但是有人可以回答为什么这样做有效而不适用于:

对象

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

和func

        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);

8 个答案:

答案 0 :(得分:10)

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

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

对于它的价值,这里更短的LINQ版本也绕过了核心问题:

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

答案 1 :(得分:4)

您可以使用JoinSelect以及Format

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

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

答案 2 :(得分:3)

您可以更轻松:将每个逗号替换为%,%

string s = "keepsakes,table runners,outdoor accessories";
string s2 = "%" + s.Replace("," , "%,%") + "%";

答案 3 :(得分:2)

另一种方法(没有lambdas):

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

答案 4 :(得分:2)

另一种方法可能是使用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));

编辑:

它使用类来分配字符串的原因是因为当你在第一个实例中使用foreach时:

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

x,键的元素(字符串)是通过值传递给函数ForEach的引用。以此为例:

var myString = "I'm a string";

Console.WriteLine(myString);

ChangeValue(myString);

Console.WriteLine(myString);

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

如果您运行该代码段,您会看到在方法ChangeValue中不会更改myString,因为我们正在尝试替换引用。方法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将更改为“其他内容”。 Here是对值

传递引用类型的一个很好的解释

答案 5 :(得分:1)

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

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

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

答案 6 :(得分:1)

正如其他人所说,传递给List.ForEach的lambda不会返回值。

LINQ很懒,但String.Join会强制枚举:

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

答案 7 :(得分:1)

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);