LINQ: how to do "flat" collection instead of "nested" [duplicate] - linq

I have a LINQ query which returns IEnumerable<List<int>> but i want to return only List<int> so i want to merge all my record in my IEnumerable<List<int>> to only one array.
Example :
IEnumerable<List<int>> iList = from number in
(from no in Method() select no) select number;
I want to take all my result IEnumerable<List<int>> to only one List<int>
Hence, from source arrays:
[1,2,3,4] and [5,6,7]
I want only one array
[1,2,3,4,5,6,7]
Thanks

Try SelectMany()
var result = iList.SelectMany( i => i );

With query syntax:
var values =
from inner in outer
from value in inner
select value;

iList.SelectMany(x => x).ToArray()

If you have a List<List<int>> k you can do
List<int> flatList= k.SelectMany( v => v).ToList();

Like this?
var iList = Method().SelectMany(n => n);

Related

Linq : How do I test a List<bool> for condition where any one of its values == true?

I have a list,
List<bool> MyList;
MyList.Add(true);
MyList.Add(false);
MyList.Add(false);
What is a clean way to use linq to test if any value is true? I tried
MyList.Find(SomeBoolean=>SomeBoolean)
but the result is weird.
Try :
bool test = MyList.Any(x => x);
But you have to initialize your list before inserting anything.
Use Any
var anyTrue = MyList.Any(i => i);
If you want to List all the true value
List<bool> MyList = new List<bool>();
MyList.Add(true);
MyList.Add(false);
MyList.Add(false);
var listTrue = MyList.Where(c => c);
I wonder, what is your actual Class because if you want to .Find is the same result.
var b = MyList.Find(c => c)
maybe you forgot to declare the var or DataType?
myList is a list of bool
myList= getSelectedChannels();
List allTrue= myList.FindAll(a => a == true);
allTrue will be a list of bool that match the criteria (bool is true). Now just say allTrue.Count to get the number of items in that list.

How to get values after dictionary sorting by values with linq

I've a dictionary, which i sorted by value with linq, how can i get those sorted value from the sorted result i get
that's what i did so far
Dictionary<char, int> lettersAcurr = new Dictionary<char, int>();//sort by int value
var sortedDict = (from entry in lettersAcurr orderby entry.Value descending select entry);
during the debug i can see that sortedDic has a KeyValuePar, but i cant accesses to it
thanks for help
sortedDict is IEnumerable<KeyValuePair<char, int>> iterate it
Just iterate over it.
foreach (var kv in sortedDict)
{
var value = kv.Value;
...
}
If you just want the char values you could modify your query as:
var sortedDict = (from entry in lettersAcurr orderby entry.Value descending select entry.Key);
which will give you a result of IEnumerable<char>
If you want it in a dictionary again you might be tempted to
var q = (from entry in lettersAcurr orderby entry.Value descending select entry.Key).ToDictionary(x => x);
but do bare in mind that the dictionary will not be sorted, since the Dictionary(Of T) will not maintain the sorted order.

How to merge result IQueryable<T> together?

If I get two result IQueryable from different linq Query and I want to merge them together and return one as result, how to to this?
For example, if:
var q1 = (IQueryable<Person>).....;
var q2 = (IQueryable<Person>).....;
how to merge q1 and q2 together and get result like
var q = (IQueryable<Person>)q1.Union(q2);
You have it, q1.Union(q2). The Union is in the System.Linq namespace with Queryable.
You can try the Concat Method
Something like this
int[] i1 = new int[] { 1, 2, 3 };
int[] i2 = new int[] { 3, 4 };
//returns 5 values
var i3 = i1.AsQueryable().Concat(i2.AsQueryable());
//returns 4 values
var i4 = i1.AsQueryable().Union(i2.AsQueryable());
Union will only give you the DISTINCT values, Concat will give you the UNION ALL.
(q1.Union(q2)).AsQuerable()
With NHibernate Union is not possible.
You have to process on the client side instead of DB processing the union.
I convert IQueryable to IENumerable with AsEnumerable and then use Concat extension.
var allItems = q1.AsEnumerable().Concat(q2)
Regards,
Sebastian

OrderBy descending in Lambda expression?

I know in normal Linq grammar, orderby xxx descending is very easy, but how do I do this in Lambda expression?
As Brannon says, it's OrderByDescending and ThenByDescending:
var query = from person in people
orderby person.Name descending, person.Age descending
select person.Name;
is equivalent to:
var query = people.OrderByDescending(person => person.Name)
.ThenByDescending(person => person.Age)
.Select(person => person.Name);
Use System.Linq.Enumerable.OrderByDescending()?
For example:
var items = someEnumerable.OrderByDescending();
Try this:
List<int> list = new List<int>();
list.Add(1);
list.Add(5);
list.Add(4);
list.Add(3);
list.Add(2);
foreach (var item in list.OrderByDescending(x => x))
{
Console.WriteLine(item);
}
Try this another way:
var qry = Employees
.OrderByDescending (s => s.EmpFName)
.ThenBy (s => s.Address)
.Select (s => s.EmpCode);
Queryable.ThenBy
This only works in situations where you have a numeric field, but you can put a minus sign in front of the field name like so:
reportingNameGroups = reportingNameGroups.OrderBy(x=> - x.GroupNodeId);
However this works a little bit different than OrderByDescending when you have are running it on an int? or double? or decimal? fields.
What will happen is on OrderByDescending the nulls will be at the end, vs with this method the nulls will be at the beginning. Which is useful if you want to shuffle nulls around without splitting data into pieces and splicing it later.
LastOrDefault() is usually not working but with the Tolist() it will work. There is no need to use OrderByDescending use Tolist() like this.
GroupBy(p => p.Nws_ID).ToList().LastOrDefault();

Join 2 lists by order instead of condition in LINQ

How can I join 2 lists of equal lengths (to produce a 3rd list of equal length) where I do not want to specify a condition but simply rely on the order of items in the 2 lists.
Eg how can I join:
{1,2,3,4} with {5,6,7,8}
to produce:
{{1,5}, {2,6}, {3,7}, {4,8}}
I have tried the following:
from i in new []{1,2,3,4}
from j in new []{5,6,7,8}
select new { i, j }
but this produces a cross join. When I use join, I always need to specify the "on".
You could use Select in the first list, use the item index and access the element on the second list:
var a = new [] {1,2,3,4};
var b = new [] {5,6,7,8};
var qry = a.Select((i, index) => new {i, j = b[index]});
If you are using .Net 4.0, you can use the Zip extension method and Tuples.
var a = new [] {1,2,3,4};
var b = new [] {5,6,7,8};
var result = a.Zip(b, (an, bn) => Tuple.Create(an, bn));
Alternatively, you can keep them as arrays:
var resultArr = a.Zip(b, (an, bn) => new []{an, bn});
There is a half way solution, if you want to use query syntax. Half way in the sense that you need to use the Select method on both lists in order to get the indexes that you will use in the where clause.
int[] list1 = {1,2,3,4};
int[] list2 = {5,6,7,8};
var result = from item1 in list1.Select((value, index) => new {value, index})
from item2 in list2.Select((value, index) => new {value, index})
where item1.index == item2.index
select new {Value1 = item1.value, Value2 = item2.value};
The benefit with this solution is that it wont fail if the lists have different lengths, as the solution using the indexer would do.

Resources