views:

30

answers:

1

I have some trivial code that looks like this:

SortedDictionary<String, long> d = new SortedDictionary<String, long>();
// d is then populated with an expensive time-consuming process

ListBox lb = new ListBox();
lb.ItemsSource = d;                                      // THIS WORKS GREAT

Now what I'd like to do is dynamically show a subset of the dictionary without having to recompute it.

// min is assigned somewhere else
lb.ItemsSource = d.SkipWhile( kvp => kvp.Value < min );  // THIS DOESN'T WORK

.SkipWhile() returns an IEnumerable, which is great for foreach loops, but not so hot for ItemsSource.

 

A) Is there a way to pass a LINQ-like expression to a WPF control in this manner?

B) Failing that, is there a way to do something like:

// Put things back, like the .ToArray() syntax
d.SkipWhile( kvp => kvp.Value < min).ToSortedDictionary();

C) Failing that, is there a way to remove entries from the actual dictionary conditionally?

d.RemoveWhere( kvp => kvp.Value < min );

 

UPDATE: The filtering wasn't working from what I was expecting. Turns out my understanding of .SkipWhile() was incorrect based on a bum documentation source.

// This is what I was seeing and seemed strange
Console.WriteLine("Total = " + dict.Count");
Console.WriteLine(" Skip = " + dict.SkipWhile( kvp => kvp.Value < 3 ).Count());
foreach ( var kvp in dict.SkipWhile( kvp => kvp.Value < 3 ) ) {
  Console.WriteLine( kvp );
}

Resulted in:

Total = 33350
 Skip = 33350
[ 0, 1042 ]
[ 00, 52 ]
[ 000, 55 ] 
[ 001, 1 ]
[ 002, 1 ]
[ 003, 1 ]
...

I wasn't expecting the lines with .Value being less than three.

Using .Where() instead, as explained in the answer, resolved the problem.

+3  A: 

The SortedDictionary is sorted on the key, not on the value, so the SkipWhile method will not skip all items where the value is less than the minimum, it will start at the smallest key and only skip items until it finds an item where the value is larger or equal to the minimum.

If you want to filter out all items where the value is less than the minimum, use the Where method:

lb.ItemsSource = s.Where(kvp => kvp.Value < min);

This creates an expression that reads from the SortedDictionary as needed.

Guffa
Ah, that explains it! THANK YOU. The problem was in my understanding of what .SkipWhile() was doing. Your explanation helped a lot.
Walt Stoneburner