LINQ from SortedList C# - linq

I'm fairly new to C#, and completely new to LINQ.
I have an existing object of type SortedList, which I would like to filter through using LINQ. However I appear to be having issues with this, apparently as the SortedList type is not generic.
For the timebeing I've looped through the entire SortedList and manually added the objects within to a List and used LINQ to filter from there. However, that seems to me, well, rubbish.
Is there a better way to convert my SortedList to List<> (I'm not bothered about preserving the key)? Or indeed to convert my SortedList to SortedList<> perhaps?

Original SortedList class is part of Collection. Generics introduces SortedList but if you have old code, then it wont be using that.
The easiest is to use the Cast method or OfType extension method that is made available for SortedList. Those methods will give you IEnumerable list that you can apply generic Linq operations. Make sure you include using System.Linq; in the beginning then you should be able to do like below:
sortedList.Cast<int>().Where(i=>i > 5);
sortedList.OfType<Car>().Where(c=> c.Color == Color.Blue);

If you don't need to filter by Keys, just cast and filter on Values
SortedList sl = new SortedList();
sl.Add("foo", "baa");
var baas = sl.Values.Cast<string>().Where(s => s == "baa");

What about
normalList = sortedList.Items;
Does that give you the list you want?

To answer the question "Is there a better way to convert my SortedList to List<> (I'm not bothered about preserving the key)?"... Here is example, with last line as the answer, resulting in list with integers 4, 1, 3, 2:
SortedList<string,int> sortedList = new SortedList<string,int>();
sortedList.Add("One", 1);
sortedList.Add("Two", 2);
sortedList.Add("Three", 3);
sortedList.Add("Four", 4);
List<int> list = sortedList.Values.ToList();

Related

List of lists and Java 8

I have a list of class R with list of other class P
List<R> rList = getRListFromDb();
I would like to get the all the P objects in another list
List<P> result = new ArrayList<>();
I tried these, but giving me Class cast exception, saying class P cannot be converted to class R. By the way I have seen issue given below, but tried and could not figure it out.
How can I turn a List of Lists into a List in Java 8?
1. rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
2. rList.forEach(r -> result.addAll(r.getP()));
I would like to what is incorrect here and also would like to know different ways of getting this done in Java 8.
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::addAll);
would work if you didn't use flatMap (since addAll requires a Collection, but flatMap transforms your Stream<List<P>> to a Stream<P>.
This would work:
rList.stream().map(R::getP).forEach(result::addAll);
With flatMap it should be:
rList.stream().map(R::getP).flatMap(List::stream).forEach(result::add);
That said, the correct way is to use collect:
List<P> result = rList.stream()
.map(R::getP)
.flatMap(List::stream)
.collect(Collectors.toList());
or
List<P> result = rList.stream()
.flatMap(r -> r.getP().stream())
.collect(Collectors.toList());

Kotlin Instantiate Immutable List

I've started using Kotlin as a substitute for java and quite like it. However, I've been unable to find a solution to this without jumping back into java-land:
I have an Iterable<SomeObject> and need to convert it to a list so I can iterate through it more than once. This is an obvious application of an immutable list, as all I need to do is read it several times. How do I actually put that data in the list at the beginning though? (I know it's an interface, but I've been unable to find an implementation of it in documentation)
Possible (if unsatisfactory) solutions:
val valueList = arrayListOf(values)
// iterate through valuelist
or
fun copyIterableToList(values: Iterable<SomeObject>) : List<SomeObject> {
var outList = ArrayList<SomeObject>()
for (value in values) {
outList.add(value)
}
return outList
}
Unless I'm misunderstanding, these end up with MutableLists, which works but feels like a workaround. Is there a similar immutableListOf(Iterable<SomeObject>) method that will instantiate an immutable list object?
In Kotlin, List<T> is a read-only list interface, it has no functions for changing the content, unlike MutableList<T>.
In general, List<T> implementation may be a mutable list (e.g. ArrayList<T>), but if you pass it as a List<T>, no mutating functions will be exposed without casting. Such a list reference is called read-only, stating that the list is not meant to be changed. This is immutability through interfaces which was chosen as the approach to immutability for Kotlin stdlib.
Closer to the question, toList() extension function for Iterable<T> in stdlib will fit: it returns read-only List<T>.
Example:
val iterable: Iterable<Int> = listOf(1, 2, 3)
val list: List<Int> = iterable.toList()

Grails mapping sort on multiple fields :: Groovy sort on multiple map entries

Stumped on this one. In Grails it seems one cannot define a default sort on multiple columns in domain mapping a la static mapping = { sort 'prop1 desc, prop2 asc' }, or { sort([prop1:'desc', prop2:'asc']) }. Only first column gets sorted, lame.
Similarly, when trying to Groovy sort a Grails findAllBy query on multiple columns, the second sort overrides the first.
def list = [[rowNum:2,position:3],[rowNum:1,position:2],[rowNum:3,position:1]]
list.sort{it.rowNum}.sort{it.position}
Obviously missing the boat on the latter case, the groovy sort. I have seen postings re: implementing comparable, but looking for something more concise if possible.
Here is a Groovy solution. Still essentially implementing a Comparator though.
list.sort { map1, map2 -> map1.rowNum <=> map2.rowNum ?: map1.position <=> map2.position }
Thanks to the link from GreenGiant, we see that the issue is closed as fixed as of version 2.3.
There is also example code:
static mapping =
{ sort([lastname:'asc', name:'asc']) }
It is working for me in 2.4.3
You can use String.format if you know max length. I assumed max 10 lenght:
list.sort { String.format('%010d%010d', it.rowNum, it.position) }

Simple Transformation with Linq

I'm sure this is a trivial question but I couldn't find a good example. Suppose all you want to do is change one attribute for all objects in a list. I'd like to say something like:
List<SomeType> list = ...;
list.Select(x => x { x.Name = "Foo" } );
Notice the absence of the "new" keyword. I don't want to recreate objects that already exist, just execute one line of code (in this case a simple assignment) on every element of the list.
Is this possible in linq in some elegant way?
Thanks in advance!
Very easy. MSDN ForEach its actually just a method of the List class, but it allows for you to use Lambda expressions.
list.Foreach(x => x.Name = "Foo" );
It doesn't really fall under Linq if you want to mutate the collection. See Eric Lippert's post to see why.
Try List<T>.ForEach()

Linq - what locale/collation it uses to compare objects?

When I call a Linq (not Linq-for-SQL, just simple in-memory Linq) - what locale it uses to compare objects, and how can I affect it?
E.g.
string[] a = { "a", "b", ... };
string max = a.Max();
What locale is used here - current, invariant? How can I affect it?
The comparision seems to be case-insensitive, what if I want to find case-sensitive max?
It uses the implementation of IComparable<string> in string.
You could fairly easily write your own version of Max which does take an IComparer<T> for comparisons - I'm very surprised there isn't one already. Alternatively, you could use Aggregate in a somewhat cumbersome way to accomplish the same result.
I decided to take a deeper look on what happening.
Max method uses Comparer class to compare items. Comparer class in turn uses GenericComparer.Compare method. This method calls String.CompareTo method. CompareTo uses following code:
CultureInfo.CurrentCulture.CompareInfo.Compare(this, strB, CompareOptions.None);
That said, you can affect behavior of Max method by changing
Thread.CurrentThread.CurrentCulture
If it's unacceptable, you have to roll out your own version of Max as Jon suggested.
Posting my code based on Jon's suggestion:
static T Max<T>(this IEnumerable<T> coll, IComparer<T> comp)
{
return coll.Aggregate((a, b) => comp.Compare(a, b) < 0 ? b : a);
}
It can be used as
string max = coll.Max(StringComparer.OrdinalIgnoreCase);

Resources