Join 2 lists by order instead of condition in LINQ - 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.

Related

Merge two or more lists in a list?

I have two queries. I want to assign the list values ​​returned from these two queries to a single list, send it to the view and meet it in the view. My goal is to learn to work with lists in C#.
var list1 = c.ETs.Where(p => p.prop != "yes").ToList();
var list2 = c.ETs.Where(p => p.prop == "yes").ToList();
You can merge two lists into one with this:
var newList = List1
.Concat(List2)
.ToList();
Though you could drop the ToList and work directly with the IEnumerable which means you don't need to create a new object.
However, this doesn't even need to be two queries since the Where clauses of both are opposite so they include the entire table, you could do:
var list = c.ETs.ToList();
Or if you want to have two different clauses that aren't simply opposites:
var list = ct.ETs
.Where(p => p.prop == "yes" || p.prop == "no")
.ToList()` for example
This will combine the values of both lists in a single list (the final output will be stored in List1):
List1.AddRange(List2);
Hi Ahmet you can try something like this but note you will need Linq:
var list3 = List1.Concat(List2).ToList();
or if you have more than 2 lists:
var list3 = list1.Concat(list2)
.Concat(list3)
.ToList();
Another method:
var list3 = List1.AddRange(List2);
Both above will create a new list containing both lists' items.

filter elements in nested dictionary LINQ

I have the following data structure:
Dictionary<string, Dictionary<string, List<int>>> data =
new Dictionary<string, Dictionary<string, List<int>>>();
I want to filter some of the elements in that dictionary based on value in first element of the list of the inner dictionary.
for example:
{legion1
{soldier1, [10,1000]},
{soldier2, [50,1000]}
}
Now let's say I want to do foreach loop in which to work only elements where
the value of the first element of the list is less than 20
expected result in the foreach loop is:
{legion1{soldier1, [10,1000]}}
What I've tried:
I do foreach loop and then I want to use something similar:
data.where(x => x.value.where(o => o[0] < 20 ))
I always get error that that way is incorrect.
Please tell how can I solve the issue and why my way is failing.
You can filter and iterate over the result set like so:
var resultSet =
data.ToDictionary(e => e.Key,
e => e.Value.Where(x => x.Value[0] < 20)
.ToDictionary(k => k.Key, v => v.Value)
);
foreach(var item in resultSet){
var key = item.Key; // string
var values = item.Value; // Dictionary<string, List<int>>
...
...
}
The problem is that you are applying operator [] incorrectly. Moreover, since you want to use both Legion and Soldier, you should construct a tuple combining the two of them:
foreach (var t in data.SelectMany(lg => lg.Value.Select(s => new {
Legion = lg
, Soldier = s
})).Where(ls => ls.Soldier.Value[0] < 20)) {
Console.WriteLine("Legion={0} Soldier = {1}", t.Legion.Key, t.Soldier.Key);
}

Executing list of IEnumerable queries

I have multiple Link queries loading to a IEnumerable list
var queries = new List<IEnumerable<Customers>>();
queries.Add(from c in context.Customers where c.region = 'NE' select c);
queries.Add(from c in context.Customers where c.region = 'SW' select c);
//want count of customers in those two regions
var result = queries.Sum(q => Count());
However it is returning a count of the queries (2), not count of the Customers.
How can execute the List of IEnumerable queries?
The mistake is at the last line:
q => Count()
Instead of actually counting the elements in a sequence, which would be q => q.Count(), you are calling a method Count() of either a current instance or the current class.
Actually, there is no need to do two separate queries. Instead, use a single query:
var query = from c
in context.Customers
where c.region = 'NE' || c.region = 'SW'
select c;
var result = query.Count();
or, slightly shorter:
var result = context.Customers.Count(c => c.region = 'NE' || c.region = 'SW');

LINQ Get Grouped ID by condition

Hi I have a List so:
A 1
A 2
A 3
A 4
B 1
B 2
C 1
I want to select the letter that contains AT LEAST these 3 numbers: 1,2,3
So in this case would be selected the letter A.
Can you help me to write this as LINQ expression?
Thanks a lot!
First, make a collection of the numbers you require.
var required = new[] { 1, 2, 3 };
Then, group your pairings by letter.
var groupedPairings = pairings.GroupBy(p => Letter, p => Number);
Then, discard those pairings that don't have your three required items. (The logic here is "take the collection of required items, remove anything in the group, and make sure there is nothing left".)
var groupsWithRequired = groupedPairings
.Where(g => !required.Except(g).Any());
Now, if you just want the letters, you can simply do
var lettersWithRequired = groupsWithRequired.Select(g => g.Key);
or if you want a dictionary mapping from the letter to its collection of numbers, you can do
var dictionary = groupsWithRequired.ToDictionary(g => g.Key, g => g.ToArray());
var numbersForA = dictionary["A"]; // = {1, 2, 3, 4}
You could try this, although I don't feel it's the best answer:
var items = new List<Item>{
new Item{Name="A", Value=1},
new Item{Name="A", Value=2},
new Item{Name="A", Value=3},
new Item{Name="A", Value=3},
new Item{Name="A", Value=4},
new Item{Name="B", Value=1},
new Item{Name="B", Value=2},
new Item{Name="C", Value=1},
};
var values = new List<int>{1,2,3};
var query = items.GroupBy (i => i.Name)
.Where (i => i.Select (x => x.Value)
.Intersect(values).Count() == values.Count)
.Select (i => i.Key);
Where
class Item{
public string Name{get;set;}
public int Value{get;set;}
}

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.

Resources