This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
C# Syntax - Example of a Lambda Expression - ForEach() over Generic List
I would like to simplify my code and change it to something shorter and still readable code.
List<string> onlineModelsNumbers = new List<string>();
foreach (OnlineModel om in OnlineModels)
onlineModelsNumbers.Add(om.model_id.ToString());
Here I'm thinking about writing the same thing in a lambda expression. But how do I do that?
List<string> onlineModelsNumbersL = onlineModelsNumbers.ForEach(...)
or
List<string> onlineModelsNumbersL = new List<string>(onlineModelsNumbers.ForEach(...))
Any other suggestions?
List<string> onlineModelsNumbers = OnlineModels.Select(om => om.model_id.ToString()).ToList();
How about:
onlineModelsNumbers.AddRange(OnlineModels.Select(o => o.model_id.ToString());
var onlineModelsNumbers = OnlineModels.Select(m => m.model_id.ToString())
.ToList();
LINQ purposely does not come with a ForEach extension (so that LINQ functions remain pure) but it is easy to write your own that wraps a foreach.
Your code is already simple. You could consider using an implicitly-typed loop variable:
foreach(var om in OnlineModels)
{
onlineModelNumbers.Add(om.model_id.ToString());
}
Or you could use AddRange:
onlineModelNumbers.AddRange(OnlineModels.Select(om => om.model_id.ToString()));
You don't need a foreach here, select will do that for you:
IEnumerable<string> = OnlineModels.Select(x => x.model_id.ToString());
Just transform and add it as a range:
List<string> onlineModelsNumbers = new List<string>(OnlineModels.Select(om => om.model_id.ToString()));
You want to perform your "foreach" on every member of OnlineModels, and as a result want to add the model's model_id string representation to onlineModelsNumbers.
I'd expect to write the expressions as follows:
onlineModels.ForEach(om => onlineModelsNumbers.Add(om.model_id.ToString()))
Related
Suppose I've an Arraylist(arr1) like the below
"String1 is present"
"String2 is present"
"String3 is present"
i wanted to see if 'String2' is present in this arraylist. i've done something like the below:
var containsstringmatch = arr1.OfType<string>().Any(arg=>arg.Contains("String2"));
if (containsstringmatch==true)
{
IEnumerable v1 = arr1.OfType<string>().Where(arg=>arg.Contains("String2"));
foreach (string s in v1)
{
st1 = s;
}
Console.WriteLine(st1);
}
which gives me the below output which is good:
"String2 is present"
I wanted to see if this can be achieved without me using the foreach loop. Can someone please provide suggestions as to how to do it.
Thanks
If you want only to print the first string that contains the search, you can use FirstOrDefault():
var foundString = arr1.OfType<string>().FirstOrDefault(arg => arg.Contains("String2"));
Console.WriteLine(string.IsNullOrEmpty(foundString) ? "Not found" : foundString);
Also, as Aomine wrote in his answer - ArrayLists where good when we worked with .Net 1.1. Since .Net 2.0 introduced generics, ArrayLists should be avoided.
As Rufus L wrote in his comment, your current code gets the last string containing the search string, not the first. If you want the last and not the first, you can simply use LastOrDefault instead of FirstOrDefault.
I'd avoid using ArrayList in this day and age in .NET, instead, favor the List<T> (if possible).
As for:
I wanted to see if this can be achieved without me using the foreach
loop.
if by this you mean that you want to avoid the foreach construct and perform everything inline:
arr1.OfType<string>()
.Where(arg => arg.Contains("String2"))
.ToList()
.ForEach(s => Console.WriteLine(s));
or if you just want to find the last element satisfying the said criteria:
var result = arr1.OfType<string>().LastOrDefault(arg => arg.Contains("String2"));
There is no way to do this without a foreach or for loop. But you can create an extension method that will move the code out of your method.
public static class ConsoleExtensions
{
public static void WriteToConsole(this IEnumerable<string> list)
{
foreach (string item in list)
Console.WriteLine(item);
}
}
usage:
arr1.OfType<string>().Where(arg=>arg.Contains("String2")).WriteToConsole();
This question already has answers here:
C# Lambda expressions: Why should I use them?
(17 answers)
Closed 9 years ago.
Can anyone give me a good explanation of how to use Lambda and give a good example. I have seen it but I dont know what it is or does.
A lambda expression is used to create an anonymous function. Here an anonymous function is assigned to a delegate variable:
Func<int, int> increase = (a => a + 1);
You can then use the delegate to call the function:
var answer = increase(41);
Usually lambda expressions are used to send a delegate to a method, for example sending a delegate to the ForEach method so that it's called for each element in the list:
List<int> list = new List<int>();
list.Add(1);
list.Add(2);
list.ForEach(n => Console.WriteLine(n));
I did a post a while back which I hope may be of some use: http://www.dontcodetired.com/blog/?tag=/lambda+expressions
A Lambda is simply a delegate, its an anonymous function that you can create for later execution.
A Lambda Expression is an uncompiled delegate in the form of an Expression Tree that you can manipulate before compiling and executing.
http://msdn.microsoft.com/en-us/library/bb397687.aspx
Perhaps I'm being a bit simplistic, but, if I were you, to start with I'd just consider lambdas as a nice way to shorten code by removing things like nested foreach loops or top n elements.
So if you're running round hotels to find some with cheap rooms you could (assuming hotels in IEnumerable):
cheapHotels = hotels.Where(h => h.PriceFrom < 50)
Once this starts to click you can move onto something more complex, this is a random method that I can find in my current project using lambdas (probably nicked from somewhere else!):
private T DeserializeObject<T>(XmlDocument xDoc, string typeName)
{
Type type = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes()).Single(t => t.FullName == typeName);
object o;
var serializer = new XmlSerializer(typeof(T));
using (TextReader tr = new StringReader(xDoc.InnerXml))
{
o = serializer.Deserialize(tr);
tr.Close();
}
return (T)o;
}
This question already has answers here:
LINQ equivalent of foreach for IEnumerable<T>
(22 answers)
Closed 7 years ago.
I have this code and want to do the same with a linq statement.
foreach (var field in fieldExtension)
{
if (field.Name.Equals(item.Name))
{
field.Access = true;
}
}
It is easy to iterate over the list with:
fieldExtension.Where(field => field.Name.Equals(item.Name));
But is it posible to assign a value to the variable we have found in the list? I thought about something like this:
fieldExtension.Where(field => field.Name.Equals(item.Name)).Select(field => field.Access = true);
Does anybody know a way to do it correctly with linq? Because I don't want to split it up. Which would also work.
var result = fieldExtension.Where(field => field.Name.Equals(item.Name)).ToList();
result.FirstOrDefault().Access = true;
Why do you insist on linq? its not a good practice to use linq alll the time.
How ever you can mix linq with foreach.
foreach (var field in fieldExtension.Where(f => f.Name.Equals(item.Name)))
{
field.Access = true;
}
I have a List which is returned to me from a 3rd party. Each string in the list ends in "mph" and I would like to remove the "mph". The obvious answer is to foreach over the list but I didn't know if there was a more efficient way to do it.
Thanks.
in a word, no. Something has to pass over the list in order to modify it. A for loop is probably the most efficient way though not necessarily the most concise
You have to iterate over the list to touch each item and make a change.
The easiest way to do this is via linq:
var originallist = new List<string> { "50mph", "35mph", "100mph" };
var newlist = list.Select(s => s.Substring(0, s.Length - 3));
You can use LINQ instead of a foreach loop:
list.Select( s => s.Substring(0, s.Length - 3) )
you can use LINQ for that purpose. Something like this might works :
var noMph = theList.Select(p => p.Replace("mph", "").ToList();
Simple Answer : You Can't
One way or another you have to perform a iteration.
it may be :
foreach
for
List.ForEach
Well you can write
mylist.Select(s=>s.Substring(0, s.Length-3));//Can add .ToList() here
But that is using a loop. You don't have to write the foreach at least :)
this will work
List<string> newList = new List<string>();
mylist.ForEach((item)=>
{
item=item.Replace("mph","");
newlist.Add(item);
});
Somehow I can't seem to get string replacement within a foreach loop in C# to work. My code is as follows :
foreach (string s in names)
{
s.Replace("pdf", "txt");
}
Am still quite new to LINQ so pardon me if this sounds amateurish ;)
You say you're after a LINQ solution... that's easy:
var replacedNames = names.Select(x => x.Replace("pdf", "txt"));
We don't know the type of names, but if you want to assign back to it you could potentially use ToArray or ToList:
// If names is a List<T>
names = names.Select(x => x.Replace("pdf", "txt")).ToList();
// If names is an array
names = names.Select(x => x.Replace("pdf", "txt")).ToArray();
You should be aware that the code that you've posted isn't using LINQ at all at the moment though...
Strings in C# are immutable (does not change), so s.Replace will return a new string. Unfortunately this means you cannot use foreach to do the update. If names is an array this should work:
for(int i = 0; i < names.Length; i++)
{
names[i] = names[i].Replace("pdf", "txt");
}
As others have mentioned you'd need to use a for loop to do this in-place. However, if you don't need the operation to be done in-place (i.e. the results can be a different collection), then you could also do it as a linq query, e.g.
var results = from name in names select name.Replace("pdf", "txt");
One thing though - it looks like you are trying to change the extension of some file names. If that's what you are trying to do then I'd recommend Path.ChangeExtension which is specifically designed for this purpose.
var results = from name in names select Path.ChangeExtension(name, "txt");
s.Replace is a function so you would like s=s.Replace().. although it's better to use StringBuilder. (see upper answer)
Why use replace? It will make the application slow. Use regex instead:
http://msdn.microsoft.com/en-us/library/system.text.regularexpressions.regex.replace.aspx