I have a class PlaceInfo that contains a private field of type Result. in the constructor of PlaceInfo i take parameter of type Result.
Now my JsonConvert.DeserializeObject<SearchFind>(JsonData); statement provides me Result[] in res.Results.
I have to construct a List<PlaceInfo>.
The simplest and thumb logical way is given below (that i am using currently).
foreach (var serverPlace in res.Results)
lstPlaces.Add(new PlaceInfo(serverPlace));
Can anyone suggest me advanced constructs?
You can use LINQ:
lstPlaces = res.Results.Select(x => new PlaceInfo(x)).ToList();
remember to add using System.Linq at the top of the file.
You could use the Linq Select and ToList method
Result[] results = ...
List<PlaceInfo> places = results.Select(x => new PlaceInfo(x)).ToList();
The Select method is a projection, applying the given function to all the elements in your array. The ToList method takes the resultant IEnumerable and creates a List.
Related
Excuse me, a quick question:
I have a list of strings, string are full paths of some files. I would like to get only the filename without the path neither the extension for each string (and to understand lambda more)
Based on the lambda expression in How to bind a List to a DataGridView control? I am trying something like the below:
FilesName = Directory.GetFiles(fbd.SelectedPath).ToList(); // full path
List<string> FilesNameWithoutPath = AllVideosFileNames.ForEach(x => Path.GetFileNameWithoutExtension(x)); // I want only the filename
AllVideosGrid.DataSource = FilesNameWithoutPath.ConvertAll(x => new { Value = x }); // to then bind it with the grid
The error is:
Can not convert void() to List of string
So I want to apply Path.GetFileNameWithoutExtension() for each string in FilesName. And would appreciate any extra description on how Lamba works in this case.
ForEach will execute some code on each item in your list, but will not return anything (see: List<T>.ForEach Method). What you want to do is Select the result of the method (see: Enumerable.Select<TSource, TResult> Method), which would look something like:
List<string> FilesNameWithoutPath = AllVideosFileNames
.Select(x => Path.GetFileNameWithoutExtension(x))
.ToList();
You are using List<T>.ForEach method which takes each element in the list and applies the given function to them, but it doesn't return anything. So what you are doing basically is getting each file name and throwing them away.
What you need is a Select instead of ForEach:
var fileNamesWithoutPath = AllVideosFileNames
.Select(x => Path.GetFileNameWithoutExtension(x))
.ToList();
AllVideosGrid.DataSource = fileNamesWithoutPath;
This will project each item, apply Path.GetFileNameWithoutExtension to them and return the result, then you put that result into a list by ToList.
Note that you can also shorten the Select using a method group without declaring a lambda variable:
.Select(Path.GetFileNameWithoutExtension)
Instead of writing a 4 line loop I would like to create a new List (Actually an IEnumerable) in place with LINQ. I know that I can supply a lambda expression to LINQ and it will map elements of a list using that expression, but will it change the type the List holds?
// My List of objects
List<MyDBDocType> myDBDocs = ...;
// How they are mapped
BsonDocument myDBDocAsBson = myDBDocs[0].ToBsonDocument();
// Function signature that takes a List that holds a separate type
MyDocCollection.InsertManyAsync([IEnumerable<BsonDocument> documents], ...);
LINQ has some methods, some will change the data type while some others will not.
For example, Select clause could change the data type:
//suppose your MyDBDocType has property called MyInt with data type: int
var result = myDBDocs.Select(x => x.MyInt); //this will result in IEnumerable<int>
But Where method retains the data type, it just filters the result according to the lambda expression:
var result = myDBDocs.Select(x => x.MyInt > 3); //this will result in IEnumerable<MyDBDocType>
Other LINQ methods like First, Last, FirstOrDefault, Except, Intersect, Distinct, Skip, SkipWhile, etc... also do not change the data type. But method like Select and SelectMany change the data type.
In your case, if you only want to filter certain results from the original query without having any change on the data type, consider using Where
C# Array, How to make data in an array distinct from each other?
For example
string[] a = {"a","b","a","c","b","b","c","a"};
how to get
string[]b = {"a","b","c"}
Easiest way is the LINQ Distinct() command :
var b = a.Distinct().ToArray();
You might want to consider using a Set instead of an array. Sets can't contain duplicates so adding the second "a" would have no effect. That way your collection of characters will always contain no duplicates and you won't have to do any post processing on it.
var list = new HashSet<string> { };
list.Add("a");
list.Add("a");
var countItems = list.Count(); //in this case countItems=1
An array, which you start with, is IEnumerable<T>. IEnumerable<T> has a Distinct() method which can be used to manipulate the list into its distinct values
var distinctList = list.Distinct();
Finally,IEnumerable<T> has a ToArray() method:
var b = distinctList.ToArray();
I think using c# Dictionary is the better way and I can sort by value using LINQ
Lets say we have a simple class
public class Foo
{
public string FooName;
}
Now we want to do some simple work on it.
public void SomeCallerMethod(List<Foo> listOfFoos)
{
string[] fooNames = listOfFoo. // What to do here?
}
If I even knew what method to call, I could probably find the rest of the peices.
You want to transform a list of your class into an array of strings. The ideal method for this is Select, which operates on each element on the enumerable and builds a new enumerable based on the type you return.
You need to put a lambda expression into the select method that returns the name, which will simply be "for each element, select the name".
You then need to cast the output as an array.
string[] fooNames = listOfFoos.Select(foo => foo.FooName).ToArray();
Or, using the other syntax:
string[] fooNames = (from foo in listOfFoos
select foo.FooName).ToArray();
This is a long shot, I know...
Let's say I have a collection
List<MyClass> objects;
and I want to run the same method on every object in the collection, with or without a return value. Before Linq I would have said:
List<ReturnType> results = new List<ReturnType>();
List<int> FormulaResults = new List<int>();
foreach (MyClass obj in objects) {
results.Add(obj.MyMethod());
FormulaResults.Add(ApplyFormula(obj));
}
I would love to be able to do something like this:
List<ReturnType> results = new List<ReturnType>();
results.AddRange(objects.Execute(obj => obj.MyMethod()));
// obviously .Execute() above is fictitious
List<int> FormulaResults = new List<int>();
FormulaResults.AddRange(objects.Execute(obj => ApplyFormula(obj)));
I haven't found anything that will do this. Is there such a thing?
If there's nothing generic like I've posited above, at least maybe there's a way of doing it for the purposes I'm working on now: I have a collection of one object that has a wrapper class:
class WrapperClass {
private WrappedClass wrapped;
public WrapperClass(WrappedClass wc) {
this.wrapped = wc;
}
}
My code has a collection List<WrappedClass> objects and I want to convert that to a List<WrapperClass>. Is there some clever Linq way of doing this, without doing the tedious
List<WrapperClass> result = new List<WrapperClass>();
foreach (WrappedClass obj in objects)
results.Add(new WrapperClass(obj));
Thanks...
Would:
results.AddRange(objects.Select(obj => ApplyFormula(obj)));
do?
or (simpler)
var results = objects.Select(obj => ApplyFormula(obj)).ToList();
I think that the Select() extension method can do what you're looking for:
objects.Select( obj => obj.MyMethod() ).ToList(); // produces List<Result>
objects.Select( obj => ApplyFormula(obj) ).ToList(); // produces List<int>
Same thing for the last case:
objects.Select( obj => new WrapperClass( obj ) ).ToList();
If you have a void method which you want to call, here's a trick you can use with IEnumerable, which doesn't have a ForEach() extension, to create a similar behavior without a lot of effort.
objects.Select( obj => { obj.SomeVoidMethod(); false; } ).Count();
The Select() will produce a sequence of [false] values after invoking SomeVoidMethod() on each [obj] in the objects sequence. Since Select() uses deferred execution, we call the Count() extension to force each element in the sequence to be evaluated. It works quite well when you want something like a ForEach() behavior.
If the method MyMethod that you want to apply returns an object of type T then you can obtain an IEnumerable<T> of the result of the method via:
var results = objects.Select(o => o.MyMethod());
If the method MyMethod that you want to apply has return type void then you can apply the method via:
objects.ForEach(o => o.MyMethod());
This assumes that objects is of generic type List<>. If all you have is an IEnumerable<> then you can roll your own ForEach extension method or apply objects.ToList() first and use the above syntax .
The C# compiler maps a LINQ select onto the .Select extension method, defined over IEnumerable (or IQueryable which we'll ignore here). Actually, that .Select method is exactly the kind of projection function that you're after.
LBushkin is correct, but you can actually use LINQ syntax as well...
var query = from o in objects
select o.MyMethod();
You can also run a custom method using the marvelous Jon Skeet's morelinq library
For example if you had a text property on your MyClass that you needed to change in runtime using a method on the same class:
objects = objects.Pipe<MyClass>(class => class.Text = class.UpdateText()).ToList();
This method will now be implemented on every object in your list. I love morelinq!
http://www.hookedonlinq.com/UpdateOperator.ashx has an extended Update method you can use. Or you can use a select statement as posted by others.