List inside a list in linq - what is it? - c#

My friends were having discussion on nested lists of objects in LINQ and when I asked what does that mean, they laughed :(
Can anyone here tell what is nested list. is it same like list inside list? Thank you to all who help me
Is this NestedList?
public class X
{
public Y[] y { get; set; }
}
public class Y
{
int id { get; set; }
}

Yes, it sounds like a list inside a list, for example:
List<List<int>>
It wasn't nice to laugh at you though - it may indicate your code is better organized into logical classes. Such constructs, in general, should be avoided - you probably wouldn't want to expose or use an interface with too complicated types, but it is common to use such lists locally, specially when using LINQ.
A simple example where this can be useful would be:
string[] directories = Directory.GetDirectories("c:\\");
var files = directories.Select(Directory.GetFiles).ToList();
Here, files is a List holding an array of strings: List<string[]>, which is quite similar. It is very likely your friends weren't talking about lists in particular, it is just as common you work with arrays, dictionaries, or IEnumerables.
The posted code does not have nested, or two dimensional lists. X has a array of Y, and that's it. If you has a list of Xs, however, that would have nested lists:
IEnumerable<X> xfiles = GetXFiles();
foreach(X file in xfiles)
{
foreach(Y section in file)
{
//...
}
}
It comes down to a simple point: an object can hold other objects, with any complexity.

they may mean a List of Lists, such as
List<List<String>> listoflists = new List<List<String>>();
listoflists.Add(new List<String>(new string[]{"One","Two"}));
listoflists.Add(new List<String>(new string[]{"A","B","C"}));

Related

Removing special type from list that contains multiple types C#

The problem I have is that I want to remove a certain item from my list that contains 2 different type. Whatever I try I just get errors and that I can use types, if I create a new instance of that class it won't delete the old. I'm really stuck here, I have no idea on what I should do.
private List<Toys> toys = new List<Toys>();
toys.Add(new Ball("red"));
toys.Add(new MouseToy("gray"));
public abstract class Toys {}
public class Ball : Toys {}
public class MouseToy : Toys {}
//how do i remove only one of the types?
//beacuse this does not work witch is one of many things i tried
foreach(var toy in toys){
if (toy.GetType == Ball){
toys.Remove(toy)
}
}
That's pretty much the code I use for the list.
You could do just:
toys = toys.Where(toy=>!(toy is Ball)).ToList();
As mentioned #Sefe in comments (thanks): you could use do it even simple and better with
List<MouseToy> mouseToys = toys.OfType<MouseToy>().ToList();
If it's ok for you that your new collection will be List<MouseToy> not List<Toys> . And that won't work if you will get a third class CatToy and you will still want to get all items, but not of Ball class
You have two issues with your solution:
You are modifying the list you are iterating with foreach. That will cause an InvalidOperationException.
.GetType == Ball does not work like this. Use is instead.
Try this:
foreach(var toy in toys.ToArray()){
if (toy is Ball){
toys.Remove(toy);
}
}
You can also use LINQ:
foreach(var toy in toys.OfType<Ball>().ToArray()){
toys.Remove(toy);
}
You cannot remove items from a list while iterating over that same list. You can either use a reverse for loop (i.e. loop descending):
for (int i = toys.Length - 1; i >= 0; i--)
{
if (toys[i] is Ball)
{
toys.RemoveAt(i);
}
}
...or you can use one of the methods defined in the System.Linq namespace. Maksim Simkin shows how to use the Where method; you could also use the OfType and Except methods:
toys = toys.Except(toys.OfType<Ball>())
.ToList();

Is there a LINQ method to join/concat an unknown number of lists?

I have an object that contains a list of child objects, each of which in turn contains a list of children, and so on. Using that first generation of children only, I want to combine all those lists as cleanly and cheaply as possible. I know I can do something like
public List<T> UnifiedListOfTChildren<T>()
{
List<T> newlist = new List<T>();
foreach (childThing in myChildren)
{
newlist = newlist.Concat<T>(childThing.TChildren);
}
return newlist;
}
but is there a more elegant, less expensive LINQ method I'm missing?
EDIT If you've landed at this question the same way I did and are new to SelectMany, I strongly recommend this visual explanation of how to use it. Comes up near the top in google results currently, but is worth skipping straight to.
var newList = myChildren.SelectMany(c => c.TChildren);

Ideal c# reduction method for values of the same type, with bitwise approach?

Good day all,
I have a class and a property, and I have three instances of that class.
public class myclass {
public int myproperty;
}
...
myclass inst1, inst2, inst3;
...
Now at a certain point I need to compare those three property values, and verify that they be equal or not, to end up with the least amount of values.
So if I have
inst1.myproperty = 3;
inst2.myproperty = 5;
inst3.myproperty = 3;
after the magic_function_call, I should get 3 and 5.
And if I have
inst1.myproperty = 2;
inst2.myproperty = 2;
inst3.myproperty = 2;
after the magic_function_call, I should get 2.
Albeit this is trivial per se, and can be solved with as many IF checks as needed, I was wondering which is the fastest, or more efficient way to do it, especially in light of the fact that I might need to add another variable to the check in the future.
I am in fact wondering if there is a bitwise operation that can be performed that can solve this elegantly and quickly.
Alternatively, is there an array operation that can be used to achieve the same goal? I've tried looking for 'reduction' or 'compression' but those keywords don't seem to lead in the right direction.
Thanks in advance.
You can use the morelinq DistinctBy query operator if all of the instances belong to a collection:
List<MyClass> myList = new List<MyClass>();
.. populate list
List<MyClass> distinct = myList.DistinctBy(mc => mc.myproperty).ToList();
Looking at the question, you may want a list of just the property values (a list of ints), which you can achieve with the standard query operators:
List<int> distinct = myList.Select(mc => mc.myproperty).Distinct().ToList();
Note that you haven't defined a property, you've defined a public field. To define an auto property change:
public int myproperty;
to
public int myproperty { get; set; }
Note also that PascalCasing is recommended for property and class names.
Here's a quick function which doesn't require any extra libraries and avoids the setup costs and overheads associated with LINQ:
static int[] Reduce(IEnumerable<myclass> items)
{
HashSet<int> uniqueValues = new HashSet<int>();
foreach (var item in items)
{
uniqueValues.Add(item.myproperty);
}
return uniqueValues.ToArray();
}
Pass it a collection of your myclass instances and it will return an array of unique myproperty values.
Just anohter way to implement it .
var result = myList.GroupBy(p => p.myproperty).Select(p => p.First());

C# Sort List Based on Another List

I have a class that has multiple List<> contained within it. Its basically a table stored with each column as a List<>. Each column does not contain the same type. Each list is also the same length (has the same number of elements).
For example:
I have 3 List<> objects; one List, two List, and three List.
//Not syntactically correct
List<DateTime> one = new List...{4/12/2010, 4/9/2006, 4/13/2008};
List<double> two = new List...{24.5, 56.2, 47.4};
List<string> three = new List...{"B", "K", "Z"};
I want to be able to sort list one from oldest to newest:
one = {4/9/2006, 4/13/2008, 4/12/2010};
So to do this I moved element 0 to the end.
I then want to sort list two and three the same way; moving the first to the last.
So when I sort one list, I want the data in the corresponding index in the other lists to also change in accordance with how the one list is sorted.
I'm guessing I have to overload IComparer somehow, but I feel like there's a shortcut I haven't realized.
I've handled this design in the past by keeping or creating a separate index list. You first sort the index list, and then use it to sort (or just access) the other lists. You can do this by creating a custom IComparer for the index list. What you do inside that IComparer is to compare based on indexes into the key list. In other words, you are sorting the index list indirectly. Something like:
// This is the compare function for the separate *index* list.
int Compare (object x, object y)
{
KeyList[(int) x].CompareTo(KeyList[(int) y])
}
So you are sorting the index list based on the values in the key list. Then you can use that sorted key list to re-order the other lists. If this is unclear, I'll try to add a more complete example when I get in a situation to post one.
Here's a way to do it using LINQ and projections. The first query generates an array with the original indexes reordered by the datetime values; in your example, the newOrdering array would have members:
{ 4/9/2006, 1 }, { 4/13/2008, 2 }, { 4/12/2010, 0 }
The second set of statements generate new lists by picking items using the reordered indexes (in other words, items 1, 2, and 0, in that order).
var newOrdering = one
.Select((dateTime, index) => new { dateTime, index })
.OrderBy(item => item.dateTime)
.ToArray();
// now, order each list
one = newOrdering.Select(item => one[item.index]).ToList();
two = newOrdering.Select(item => two[item.index]).ToList();
three = newOrdering.Select(item => three[item.index]).ToList();
I am sorry to say, but this feels like a bad design. Especially because List<T> does not guarantee element order before you have called one of the sorting operations (so you have a problem when inserting):
From MSDN:
The List is not guaranteed to be
sorted. You must sort the List
before performing operations (such as
BinarySearch) that require the List
to be sorted.
In many cases you won't run into trouble based on this, but you might, and if you do, it could be a very hard bug to track down. For example, I think the current framework implementation of List<T> maintains insert order until sort is called, but it could change in the future.
I would seriously consider refactoring to use another data structure. If you still want to implement sorting based on this data structure, I would create a temporary object (maybe using an anonymous type), sort this, and re-create the lists (see this excellent answer for an explanation of how).
First you should create a Data object to hold everything.
private class Data
{
public DateTime DateTime { get; set; }
public int Int32 { get; set; }
public string String { get; set; }
}
Then you can sort like this.
var l = new List<Data>();
l.Sort(
(a, b) =>
{
var r = a.DateTime.CompareTo(b);
if (r == 0)
{
r = a.Int32.CompareTo(b);
if (r == 0)
{
r = a.String.CompareTo(b);
}
}
return r;
}
);
I wrote a sort algorithm that does this for Nito.LINQ (not yet released). It uses a simple-minded QuickSort to sort the lists, and keeps any number of related lists in sync. Source code starts here, in the IList<T>.Sort extension method.
Alternatively, if copying the data isn't a huge concern, you could project it into a LINQ query using the Zip operator (requires .NET 4.0 or Rx), order it, and then pull each result out:
List<DateTime> one = ...;
List<double> two = ...;
List<string> three = ...;
var combined = one.Zip(two, (first, second) => new { first, second })
.Zip(three, (pair, third) => new { pair.first, pair.second, third });
var ordered = combined.OrderBy(x => x.first);
var orderedOne = ordered.Select(x => x.first);
var orderedTwo = ordered.Select(x => x.second);
var orderedThree = ordered.Select(x => x.third);
Naturally, the best solution is to not separate related data in the first place.
Using generic arrays, this can get a bit cumbersome.
One alternative is using the Array.Sort() method that takes an array of keys and an array of values to sort. It first sorts the key array into ascending order and makes sure the array of values is reorganized to match this sort order.
If you're willing to incur the cost of converting your List<T>s to arrays (and then back), you could take advantage of this method.
Alternatively, you could use LINQ to combine the values from multiple arrays into a single anonymous type using Zip(), sort the list of anonymous types using the key field, and then split that apart into separate arrays.
If you want to do this in-place, you would have to write a custom comparer and create a separate index array to maintain the new ordering of items.
I hope this could help :
one = one.Sort(delegate(DateTime d1, DateTime d2)
{
return Convert.ToDateTime(d2).CompareTo(Convert.ToDateTime(d1));
});

C# Extract list of fields from list of class

I've got a list of elements of a certain class. This class contains a field.
class Foo {public int i;}
List<Foo> list;
I'd like to extract the field from all items in the list into a new list.
List<int> result = list.ExtractField (e => e.i); // imaginary
There are surely multiple ways to do that, but I did not find a nice-looking solution yet. I figured linq might help, but I was not sure how exactly.
Just:
List<int> result = list.Select(e => e.i).ToList();
or
List<int> result = list.ConvertAll(e => e.i);
The latter is more efficient (because it knows the final size to start with), but will only work for lists and arrays rather than any arbitrary sequence.

Categories

Resources