Lambda to extract some integers? - c#

List<int[]> A = ServiceItems.First()
.ServiceItemDetails.Select(x => new int[]{ x.Numbers}).ToList();
This gets me a list of integer arrays.
I need a list of plain integers
I tried this:
List<int> A = ServiceItems.First()
.ServiceItemDetails.Select(x => new int{ x.Numbers})
.ToList();
Ouch!
Cannot initialize type int with a collection....does not implement IEnumerable
How do I accomplish this and what exactly is going on here?
Thanks!

It's not clear as you haven't told us what x.Numbers is, but if the first code really gives you a List<int[]> then it may be as simple as:
List<int> A = ServiceItems.First()
.ServiceItemDetails
.Select(x => x.Numbers)
.ToList();
If that's the case, and x.Numbers really is a single int, you'd be well advised to rename it if you can - it currently sounds like a collection of numbers.

Can't you just take out the array part?
List<int> A = ServiceItems.First().
ServiceItemDetails.Select(x => x.Numbers).ToList();

Try
List<int> A = ServiceItems.First().ServiceItemDetails.SelectMany(x => x.Numbers).ToList();
SelectMany() behaves like Select() but has the effect of "flattening" the resulting collection of collection.

Do you mean that you want to flatten the list of arrays of integers into one big list of integers? Without any additional sorting/filtering/etc. you can use .SelectMany(). Something like this:
var integers = ServiceItems.First().ServiceItemDetails.SelectMany(s => s.Numbers);

I think you just need a SelectMany to flatten your list of integers like so...
List<int[]> A = ServiceItems.First().ServiceItemDetails.SelectMany(x => x.Numbers).ToList();

List<int[]> A = ServiceItems.First().ServiceItemDetails.Select(x => x.Numbers).ToList();
You need not initialize int as you would initialize class by doing new int{...}. int is a value type to which, you can assign the value directly.

Related

How correctly sort a list<string> with numbers?

I met a Difficulty to sort a list item string containing numbers.
I wish I could automatically sort from smallest to largest.
Here is my code:
// Initialize an array to store the numbers
List<string> tab_num = new List<string>();
tab_num.Add("A.3.2.1");
tab_num.Add("A.3.3.1");
tab_num.Add("A.1.0.1");
tab_num.OrderByDescending(num => num).ToList();
Why my result is false ?...
[1] A.3.2.1
[2] A.3.3.1
[3] A.1.0.1
Expected Result:
[1] A.1.0.1
[2] A.3.2.1
[3] A.3.3.1
Thanks a lot
OrderByDescending means from bigger to lower.
Also you are not assigning your result after sorting.
try this:
List<string> tab_num = new List<string>();
tab_num.Add("A.3.2.1");
tab_num.Add("A.3.3.1");
tab_num.Add("A.1.0.1");
tab_num = tab_num.OrderBy(num => num).ToList();
Because you are sorting alphabetically. You should use OrderBy anyway if you want to order "smallest to largest". You need to parse it to somewhat numerical or to version:
Version v = null;
var ordered = tab_num.Select(tab => new { tab, Versionpart = tab.Substring(2) })
.Where(x => Version.TryParse(x.Versionpart, out v))
.OrderBy(x => v)
.Select(x => x.tab)
.ToList();
(assuming that the version is always found at tab.Substring(2))
You should set result of linq query to any variable (and use OrderBy):
List<string> tab_num = new List<string>();
tab_num.Add("A.3.2.1");
tab_num.Add("A.3.3.1");
tab_num.Add("A.1.0.1");
tab_num = tab_num.OrderBy(num => num).ToList();
tab_num.OrderBy(num => num).ToList() is not perform sorting on source list, but returns sorted list.
Actually you don't need linq here, use Sort method:
tab_num.Sort();
But if you want to make your code work, just assign resulting list to a source list:
tab_num = tab_num.OrderBy(x => x).ToList();
the main problem here is that you are not assigning the result to the list as suggested below.
BTW: This list doesn't contains numbers, it contains string so the comparer uses the alphabetic comparator. you should use OrderBy not OrderByDescending. I suggest you to implement your own comparator since your strings are quite simple and the default comparator will give you wrong responses when numbers grows over 9

How do I get list of id's as int using LINQ

I have a DataTable, say pdt, in my code. I just want to select all table["id"] and populate then in an integer array.
I can go ahead with a foreach but I am trying to learn Lambda expressions.
I can't figure out how to deal with this.
I have tried
List<int> Ids = pdt.Select(row => row["Id"]; return Convert.ToInt32(r));
and
int[] Ids = pdt.Select(row => row["Id"]);
but nothing seems to work. I am pretty sure this is a basic question, help out a newbie please.
If you want an array, you need to use the ToArray() extension method... but you also want to use the DataTableExtensions.AsEnumerable() extension method to make the data table strongly typed in terms of a DataRow sequence:
int[] ids = pdt.AsEnumerable()
.Select(r => (int) r["Id"])
.ToArray();
EDIT: As noted in abatishchev's answer, an alternative to the explicit cast here would be to use the Field<T> extension method (in DataRowExtenions):
int[] ids = pdt.AsEnumerable()
.Select(r => r.Field<int>("Id"))
.ToArray();
Use type-safe call:
r.Field<string>("Id")

Lambda expression for getting items from list according to indexes

Is it possible to get objects from a list according to their indexes at one shot? For example I have a List<string> alist. I have an integer List List<int> indexes which has indexes. Is it possible to get a result list from the original list which equals the indexes in the array.
I am looking for something like List<string> resultlist = alist.GetItems(items.indexin(indexes)) (that's just my imagination, not the actual syntax-sorry)
Something like this should work:
var result = indexes.Select(i => alist[i]).ToList();
Of course, I recommend you make it a bit more robust.
var result = alist.Where((theString, theIndex) => indexes.Contains(theIndex));
indexes.Select<int, string>(i => alist[i]).ToList<string>();

Sort one list by another

I have 2 list objects, one is just a list of ints, the other is a list of objects but the objects has an ID property.
What i want to do is sort the list of objects by its ID in the same sort order as the list of ints.
Ive been playing around for a while now trying to get it working, so far no joy,
Here is what i have so far...
//**************************
//*** Randomize the list ***
//**************************
if (Session["SearchResultsOrder"] != null)
{
// save the session as a int list
List<int> IDList = new List<int>((List<int>)Session["SearchResultsOrder"]);
// the saved list session exists, make sure the list is orded by this
foreach(var i in IDList)
{
SearchData.ReturnedSearchedMembers.OrderBy(x => x.ID == i);
}
}
else
{
// before any sorts randomize the results - this mixes it up a bit as before it would order the results by member registration date
List<Member> RandomList = new List<Member>(SearchData.ReturnedSearchedMembers);
SearchData.ReturnedSearchedMembers = GloballyAvailableMethods.RandomizeGenericList<Member>(RandomList, RandomList.Count).ToList();
// save the order of these results so they can be restored back during postback
List<int> SearchResultsOrder = new List<int>();
SearchData.ReturnedSearchedMembers.ForEach(x => SearchResultsOrder.Add(x.ID));
Session["SearchResultsOrder"] = SearchResultsOrder;
}
The whole point of this is so when a user searches for members, initially they display in a random order, then if they click page 2, they remain in that order and the next 20 results display.
I have been reading about the ICompare i can use as a parameter in the Linq.OrderBy clause, but i can’t find any simple examples.
I’m hoping for an elegant, very simple LINQ style solution, well I can always hope.
Any help is most appreciated.
Another LINQ-approach:
var orderedByIDList = from i in ids
join o in objectsWithIDs
on i equals o.ID
select o;
One way of doing it:
List<int> order = ....;
List<Item> items = ....;
Dictionary<int,Item> d = items.ToDictionary(x => x.ID);
List<Item> ordered = order.Select(i => d[i]).ToList();
Not an answer to this exact question, but if you have two arrays, there is an overload of Array.Sort that takes the array to sort, and an array to use as the 'key'
https://msdn.microsoft.com/en-us/library/85y6y2d3.aspx
Array.Sort Method (Array, Array)
Sorts a pair of one-dimensional Array objects (one contains the keys
and the other contains the corresponding items) based on the keys in
the first Array using the IComparable implementation of each key.
Join is the best candidate if you want to match on the exact integer (if no match is found you get an empty sequence). If you want to merely get the sort order of the other list (and provided the number of elements in both lists are equal), you can use Zip.
var result = objects.Zip(ints, (o, i) => new { o, i})
.OrderBy(x => x.i)
.Select(x => x.o);
Pretty readable.
Here is an extension method which encapsulates Simon D.'s response for lists of any type.
public static IEnumerable<TResult> SortBy<TResult, TKey>(this IEnumerable<TResult> sortItems,
IEnumerable<TKey> sortKeys,
Func<TResult, TKey> matchFunc)
{
return sortKeys.Join(sortItems,
k => k,
matchFunc,
(k, i) => i);
}
Usage is something like:
var sorted = toSort.SortBy(sortKeys, i => i.Key);
One possible solution:
myList = myList.OrderBy(x => Ids.IndexOf(x.Id)).ToList();
Note: use this if you working with In-Memory lists, doesn't work for IQueryable type, as IQueryable does not contain a definition for IndexOf
docs = docs.OrderBy(d => docsIds.IndexOf(d.Id)).ToList();

Trouble casting results of Select() to a List<T>

What am I missing here?
I want to do a simple call to Select() like this:
List<int> list = new List<int>();
//fill the list
List<int> selections = (List<int>)list.Select(i => i*i); //for example
And I keep having trouble casting it. What am I missing?
Select() will return you an IEnumerable<int> type, you have to use the ToList() operator:
List<int> selections = list.Select(i => i*i).ToList();
Select() doesn't return a List so of course you can't cast it to a list.
You can use the ToList method instead:
list.Select(i => i*i).ToList();
As others have said, Select returns an IEnumerable<T> which isn't actually a list - it's the result of a lazily-evaluated iterator block.
However, if you're dealing with lists and you want a list back out with nothing other than a projection, using List<T>.ConvertAll will be more efficient as it's able to create the new list with the right size immediately:
List<int> selections = list.ConvertAll(i => i*i);
Unless you particularly care about the efficiency, however, I'd probably stick to Select as it'll give you more consistency with other LINQ code.

Categories