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();
Related
I have an array of type Brick with each brick having an isBroken bool property. How can I use Linq to filter all bricks with isBroken = true into a new array?
Use Where to filter the list of bricks and ToArray to materialize the result into a new array.
var result = MyBricksArray.Where(x => x.isBroken).ToArray();
I hope this example will explain things more clearly, Let the definition of your class will be like the following:
public class Brick
{
public string Name;
public bool isBroken ;
}
And the Array of it's objects is defined like this:
Brick[] BrickArray =new Brick[]{
new Brick(){Name="A",isBroken=true},
new Brick(){Name="B",isBroken=true},
new Brick(){Name="C",isBroken=false}};
Then you can use the .Where to filter the collection like the following:
var selectedBriks = BrickArray.Where(x=>x.isBroken).ToList();
Now the selectedBriks will contains the items with name A and B
You can use the select method for this :
var theNewList = Brick.Where(b => b.isBroken).Select(b => new Brick
{
//Populate new object
}).ToList() / .ToArray();
Note that Select is used and not where to project the List into a new one.
Also, the .ToList()/ToArray() is to add the array to memory, you may not need it, .Select() return an IEnumerable.
It is possible to use Brik.Where(..).ToList(); as this would create a new List but the reference to the object inside the list would be the same, so again it depands on your need.
And .Select() require using System.Linq;
In C#, I have a string array that I have written full full of "getter" method calls. They call methods in another class so that the array is populated with the needed strings. It looks something like this:
string[] mCalls = {c.get1(), c.get2(), c.get3()};
I'm sure this situation could apply to any program. However, in my program the variables these methods return are initially set with the string "Unchecked" - thus filling this example array with Unchecked 3 times. As my program goes on and things are checked, the values of the string variables get changed within the class they're in. I've been simply re-calling the getter methods at appropriate times to change what's in my array, like this:
mCalls[0] = c.get1();
mCalls[1] = c.get2();
mCalls[2] = c.get3();
I don't really like this. It seems inevitable that one day I'll have to change something, and if that happens I will have to manually do the tedious work of changing all of the indexing throughout my program. If this happens to be the best way I'm fine with that, but I assume there are better ways. So, in any case, is there a way to "refresh" the values in an array that is set up like this? And if so, what is it?
You want something like this:
public string[] MCalls
{
get
{
return new string[]{c.get1(), c.get2(), c.get3()};
}
private set;
}
and then use MCalls as if it is a regular variable whenever you want to access the arrays
You could change your array to contain functions instead of strings like this:
Func<string>[] mCalls = { c.get1, c.get2, c.get3...};
And then use it this way:
string c2 = mCalls[1]();
But note that this way every access is a method call. I'm not sure what you are really trying to achieve, there may be better overall designs than this approach.
Couple of options:
Create an array of lambdas:
var mCalls = new Func<object, string>[] {
(object o) => o.ToString() ,
(object o) => o.GetHashCode().ToString(),
(object o) => o.GetType().ToString(),
};
If the input to each lambda is the same you can create a lambda that returns an array:
Func<object, string[]> GetValues = (object o) => new string[]
{
o.ToString() ,
o.GetHashCode().ToString(),
o.GetType().ToString(),
};
Then just reload the array by calling the lambda:
mCalls = GetValues(c);
Note that it isn't technically refreshing the array, it's creating a new array. If you need to keep the array the same but just update the values you'd ned to loop through the array and assign the values by index.
What you could do is loop thorugh with reflection and get all methods from the class and from here you can get a list of method names. With this list you can assign to an array or run the methods by name or whatever. You can also filter the list to get your specific method names only:
var methodNames = typeof(MyClass).GetMethods(BindingFlags.Public | BindingFlags.Static)
.Select(x => x.Name)
.Distinct()
.OrderBy(x => x);
To call the methods:
foreach(var method in methodNames)
{
typeof(MyClass).GetMethod(method).Invoke(t, new[] { "world" });
}
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.
I have to write a query in a web application using LINQ but I need to change that query into an array list. How can I change the query below to do this?
var resultsQuery =
from result in o["SearchResponse"]["Web"]["Results"].Children()
select new
{
Url = result.Value<string>("Url").ToString(),
Title = result.Value<string>("Title").ToString(),
Content = result.Value<string>("Description").ToString()
};
If you really need to create an ArrayList, you can write new ArrayList(resultsQuery.ToArray()).
However, you should use a List<T> instead, by writing resultsQuery.ToList().
Note that, in both cases, the list will contain objects of anonymous type.
There is a .ToArray() method that'll convert IEnumerable to an Array.
ArrayList doesn't have a constructor or Add(Range) method that takes an IEnumerable. So that leaves two choices:
Use an intermediate collection that does implement ICollection: as both Array and List<T> implement ICollection can be used via the ToArray() or ToList() extension methods from LINQ.
Create an instance of ArrayList and then add each element of the result:
var query = /* LINQ Expression */
var res = new ArrayList();
foreach (var item in query) {
res.Add(item);
}
The former method is simple to do but does mean creating the intermediate data structure (which of the two options has a higher overhead is an interesting question and partly depends on the query so there is no general answer). The latter is more code and does involve growing the ArrayList incrementally (so more memory for the GC, as would be the case for an intermediate Array or List<T>).
If you just need this in one place you can just do the code inline, if you need to do it in multiple places create your own extension method over IEnumerable<T>:
public static class MyExtensions {
public static ArrayList ToArrayList<T>(this IEnumerable<T> input) {
var col = input as ICollection;
if (col != null) {
return new ArrayList(col);
}
var res = new ArrayList();
foreach (var item in input) {
res.Add(item);
}
return res;
}
}
Say I have the following class:
class Foo
{
// ctor etc here
public string Bar
{
get;
}
}
Now, I have a LinkedList of Foos declared like so: LinkedList<Foo>
How would I write a basic Contains<>() for this?
I want to be able to do this:
Foo foo = new Foo(someString);
LinkedList<Foo> list = new LinkedList<foo>();
// Populate list with Foos
bool contains = list.Contains<Foo>(foo, (x => foo.Bar == x.Bar));
Am I trying to do this correctly?
Thanks
If you want to use LinkedList.Contains, you can do that, but Foo but implement IEquatable<Foo>. LinkedList.Contains does not work via a Predicate function, but rather by searching for a specific element. To use Contains, you would write:
bool contains = list.Contains(foo);
However, in this case, you may want to consider using the Enumerable.Any() extension method instead of Contains(). Doing this, it will look like your previous code, except you don't need the first "foo":
Foo foo = new Foo(someString);
LinkedList<Foo> list = new LinkedList<foo>();
// Populate list with Foos
bool contains = list.Any(x => foo.Bar == x.Bar);
Since "foo" is visible in the current scope, when you create the lambda expression, the compiler will automatically generate a closure over the "foo" variable, allowing you to use it directly. You only need to specify the argument name (x) for use in the predicate function created in the lambda.
This requires a reference to System.Core.dll and a using System.Linq; at the top of your file, as well as .NET 3.5+.
What you want is .Any<T>() in this case. Something like this:
bool contains = list.Any(x => foo.Bar == x.Bar);
What this says is "are there any where this statement is true?" Think Count() > 0 in this case. Then you use a variable, in this case x, x stands for the current element in list that you are on while iterating through it, so for each element you're comparing and seeing if it matches.