I have the following list of Pair objects:
var listOfPairs = new List<Pair<int, List<int>>>() {
new Pair<int, List<int>>(30, new List<int>() {3, 6, 9}),
new Pair<int, List<int>>(40, new List<int>() {4, 8, 12})
};
I would like to end up with the following list of list-of-integers:
listOfPairs[0] = {30, 3, 6, 9};
listOfPairs[1] = {40, 4, 8, 12};
I've tried a lot of fiddling that looks like this, but to no avail:
var flattenedListOfPairs = listOfPairs.Select(pair => new List<int>(pair.First).AddRange(pair.Second));
I assume that what I'm trying to do is possible, and I'm just missing something.
Sounds like you might want something like:
var flattened = listOfPairs.Select(pair => new[] { pair.First }.Concat(pair.Second)
.ToList())
.ToList();
Or:
var flattened = listOfPairs.Select(pair => Enumerable.Repeat(pair.First, 1)
.Concat(pair.Second)
.ToList())
.ToList();
Or using MoreLINQ
var flattened = listOfPairs.Select(pair => pair.Second.Prepend(pair.First)
.ToList())
.ToList();
This gives you a list of lists, in the form you specified:
listOfPairs.Select(p => new []{ p.First }.Concat(p.Second).ToList()).ToList()
Other answers already covered how to do this, so I won't repeat that here. This answer is to explain why your existing code wasn't working. You expected to pass an int to the List constructor and have it initialize the List with that int. That's not how the constructor works. The List constructor uses the int argument to set up the initial size of the list, rather than set the value of any items.
Try this:
var flattenedListOfPairs = listOfPairs.Select(pair =>
{
var list = new List<int>(pair.First);
list.AddRange(pair.Second));
return list;
}.ToList();
Related
I have a dictionary with int key and List value
I would like to find out if the key or values contains a specific integer and get the related key for it.
Example:
Dictionary<int, List<int>> removableStuff = new Dictionary<int, List<int>>();
removableStuff.Add(1, new List<int> {1});
removableStuff.Add(3, new List<int> {9,33,35});
removableStuff.Add(2, new List<int> {1,65,32,3});
I would like to find the number 3.
Since the number 3 can be found as key and value, the output would be: 3, 2.
This should yield the desired result:
var num = 3;
var keys = removableStuff.Where(i => i.Key.Equals(num) || i.Value.Any(num.Equals))
.Select(i => i.Key);
You can optionally call .ToList() after the .Select(), if you don't want to deal with an Enumerable.
The i.Value.Any(num.Equals) can also be simplified to i.Value.Contains(num), but when I use Linq I like to use Any for that sort of stuff too. (Just personal preference)
Nonetheless this is very basic Linq and I'm sure you would've found your answer prior to asking, if you would've looked.
A similar method to Tobias' answer is to use Contains instead of Any(Equals):
Dictionary<int, List<int>> removableStuff = new Dictionary<int, List<int>>
{
{1, new List<int> {1}},
{3, new List<int> {9, 33, 35}},
{2, new List<int> {1, 65, 32, 3}}
};
int find = 3;
var matches = removableStuff.Where(item => item.Key == find || item.Value.Contains(find));
foreach (var match in matches)
{
Console.WriteLine($"{match.Key}: {string.Join(", ", match.Value)}");
}
I have a list of numbers and need to select rows from DB table by that order.
i was looking to implement ORDER BY FIELD() query in LinQ / lambda expressions with no luck
any ideas?
the code look like this:
using (var db = new TimeTable.EntityFramework.TimeTableEntities())
{
List<int> list = new List<int>() { 2, 1, 4, 3 };
var query = db.place_users_info.OrderBy(item => item.UniqueId);
}
I need to order the rows by the list items
if your rowcount is not that big, maybe you are looking for something like this (checks ommitted):
using (var db = new TimeTable.EntityFramework.TimeTableEntities())
{
List<int> list = new List<int>() { 2, 1, 4, 3 };
var a = db.place_users_info.ToArray();
var b = list.Select(x=>a[x]).ToList();
}
From what I understand you have (according to the example) 4 rows which you want to order by the number they have on the number list.
To do so use Zip to merge the lists by index (first item in numbers list will be with first item in the data list and so on)
using (var db = new TimeTable.EntityFramework.TimeTableEntities())
{
List<int> list = new List<int>() { 2, 1, 4, 3 };
var query = db.place_users_info.Zip(list, (f,s) => new { f,s })
.OrderBy(item => item.s)
.Select(item => item.f);
}
If you have the list, say:
var list<myobject> = <yourRepository>.<GetYourData>.ToList().OrderBy(o => o.<property>;
besides, in memory order by is probably faster then in DB.
If you would do:
var list<myobject> = <yourRepository>.<GetYourData>.OrderBy(o => o.<property>).ToList();
you would do the order by in the DB. (If your returns an IQueryable)
(See my code snippet below) I want to find all items of coll1 that matched to items of coll2 (number of items of coll2 <= number of items of coll1) and put the query result in coll3. How to achieve it using linq and lambda expression?
Surely, I can simply copy coll2 to coll3 :-) but that is not my goal. I want to know the ways using linq and lambda to replace such conventional logic construct. Thank you in advance.
var coll1 = new List<int>() { 1, 2, 3, 4, 5 };
var coll2 = new List<int>() { 2, 4 };
var coll3 = new List<int>();
foreach ( var selected in coll2 )
{
foreach ( var item in coll1 )
{
if ( selected == item )
{
coll3.Add(item);
}
}
}
You can use Intersect
coll1.Intersect(coll2);
But this wont work as expected(see King King's comment)..You can instead do this
coll2.Where(x=>coll1.Any(y=>x==y));
coll3 = coll1.Where(i => coll2.Contains(i)).ToList();
Update. A little bit simpler, as suggested in comments:
coll3 = coll1.Where(coll2.Contains).ToList();
As a first step, you can use a where clause to make your code more readable :
var coll1 = new List<int>() { 1, 2, 3, 4, 5 };
var coll2 = new List<int>() { 2, 4 };
var coll3 = new List<int>();
foreach (var selected in coll2)
{
coll3.AddRange(coll1.Where(item => selected == item));
}
Use Intersect: http://msdn.microsoft.com/en-us/library/bb460136.aspx
var coll3 = coll1.Intersect(coll2)
You could do this; not sure if it's more readable tho!
var coll3 = (from selected in coll2
from item in coll1
where selected == item
select item).ToList();
If you do not want to directly assign the result to your list, you could add 'ForEach' to your Linq statement:
coll1.Where(i => coll2.Contains(i)).ToList().ForEach(i => coll3.Add(i));
You might want to check for Distinct though
Here is function, that I use the list of permutations:
public static IEnumerable<IEnumerable<T>> Permute<T>(IEnumerable<T> list)
{
if (list.Count() == 1)
return new List<IEnumerable<T>> { list };
return list.Select((a, i1) => Permute(
list.Where((b, i2) => i2 != i1)).Select(
b => (new List<T> { a }).Union(b))
).SelectMany(c => c);
}
use it in the following way:
var SFP_vars = Permute(SFP);
Where SFP is array of bytes:
byte[] SFP = new byte[7] { 0, 1, 2, 3, 4, 5, 6 };
There is other variable:
List<byte[]> lst_SFP = new List<byte[]>();
Now my question: How to assign the value of SFP_vars to lst_SFP ?
lst_SFP = SFP_vars.ToList() doesn't work.
You need to also convert the inner enumerables to byte arrays:
lst_SFP = SFP_vars.Select(x => x.ToArray()).ToList();
lst_SFP = SFP_vars.Select(bytePermutation => bytePermutation.ToArray()).ToList()
Basically you want the things in your list to be a byte array, so the Select statement handles that, giving you an IEnumerable<byte[]>.
Then we do ToList on that to make it a list.
bytePermutation could be named anything, I just named it as such so you can get an idea of what's going on.
SFP_vars looks like an IEnumerable<IEnumerable<byte>> rather than an IEnumerable<byte[]>.
This means that the you first need to convert the IEnumerable<byte> objects to byte[] using the ToArray() method. You can then add them to the list.
Although it amounts to the same thing, you could replace with this LINQ query:
List<byte[]> lst_SFP = SFP_vars.Select(ie => ie.ToArray()).ToList();
Hope this helps.
You need to convert the inner IEnumerable<byte> into an array, this can be done using .Select(). One this is done .ToList() will return as a List<byte[]>.
var SFP = new byte[7] { 0, 1, 2, 3, 4, 5, 6 };
var SFP_vars = Permute(SFP);
var lst_SFP = SFP_vars
.Select(e => e.ToArray())
.ToList();
Unless you need a particular order though, you may be better off using the List<IEnumerable<byte>>. Using this will prevent an Array.Copy.
I have the following array of integers:
int[] array = new int[7] { 1, 3, 5, 2, 8, 6, 4 };
I wrote the following code to get the top 3 elements in the array:
var topThree = (from i in array orderby i descending select i).Take(3);
When I check what's inside the topThree, I find:
{System.Linq.Enumerable.TakeIterator}
count:0
What did I do wrong and how can I correct my code?
How did you "check what's inside the topThree"? The easiest way to do so is to print them out:
using System;
using System.Linq;
public class Test
{
static void Main()
{
int[] array = new int[7] { 1, 3, 5, 2, 8, 6, 4 };
var topThree = (from i in array
orderby i descending
select i).Take(3);
foreach (var x in topThree)
{
Console.WriteLine(x);
}
}
}
Looks okay to me...
There are potentially more efficient ways of finding the top N values than sorting, but this will certainly work. You might want to consider using dot notation for a query which only does one thing:
var topThree = array.OrderByDescending(i => i)
.Take(3);
Your code seems fine to me, you maybe want to get the result back to another array?
int[] topThree = array.OrderByDescending(i=> i)
.Take(3)
.ToArray();
Its due to the delayed execution of the linq query.
As suggested if you add .ToArray() or .ToList() or similar you will get the correct result.
int[] intArray = new int[7] { 1, 3, 5, 2, 8, 6, 4 };
int ind=0;
var listTop3 = intArray.OrderByDescending(a=>a).Select(itm => new {
count = ++ind, value = itm
}).Where(itm => itm.count < 4);