tags:

views:

78

answers:

3

I need to assign values from a small dictionary collection (10 items) to a larger number (about 20 to 30) of dropdownlists in their selected value property.

Specifically, I need to take the key of the max value in the dictionary, assign it to the first dropdownlist.selected value. Then take the key of the 2nd highest max value, assign it to the second dropdownlist. When I go through all the keys/values in the dictionary (and there's still dropdownlists needing to be assigned), I need to start back at the top using the key of the max value in the dictionary.

I'm able to get the key of the max value like so.

var maxKey = 
    results
    .Aggregate((left, right) => left.Value > right.Value ? left : right).Key;

ddlItem.SelectedValue = maxKey.ToString();

What I was doing originally was, I was removing the maxvalue after assigning it. But I forgot that there would be more dropdownlists than actual dictionary values. I'm guessing the solution is to use a different, temporary collection and work with that? Any help is appreciated.

If using a list is required, how would I transfer a dictionary to a list and use index, key, and value?

+1  A: 

Are you trying to create an IEnumerable of keys that are sorted (DESC) by value?

edit

The simplest way to do this would be:

var seq = d.OrderByDescending(kvp => kvp.Value).Select(kvp => kvp.Key);

The d is your Dictionary<string,int>. The OrderByDescending sorts the key-value pairs by diminishing value and the Select extracts the key from the pair. The result is an IEnumerable<string> in exactly the order you want.

At that point, you can run a foreach over it, or I suppose you could also load it into a Queue, as another example shows.

(The above could also be done in a more SQL-ish syntax, but I didn't see the point.)

Steven Sudit
Yes, I think that's what I'm getting at. A list or maybe an ordereddictionary collection?
Gabe
You can convert an `IEnumerable<string>` to a list with `ToList`, if desired. As for an ordered dictionary, see my response to Andrew.
Steven Sudit
Andrew deleted his answer, so just to avoid the point being lost, `OrderedDictionary` doesn't sort by key, it just allows you to retrieve by a numeric index based on the insertion order. It's `SortedDictionary` that sorts by key.
Steven Sudit
A: 

You should sort the list descending, then you can assign the first value to the first control, second value to the second control, and so on, by index.

Hope that helps!

Kieren Johnstone
How can I transfer a dictionary to a list and use index, key, and value and have it sorted?
Gabe
See Winston's answer below. The key idea I was trying to suggest was sorting rather than iteratively selecting the top then excluding it (which is sorting anyway) :)
Kieren Johnstone
+2  A: 

You can use OrderByDescending to get the key value pairs in descending order by value, eg

var d = new Dictionary<int, string>();
var orderedKeyValuePairs = d.OrderByDescending(kvp => kvp.Value);

In this example, orderedKeyValuePairs is an IOrderedEnumerable<KeyValuePair<int, string>>

In order to facilitate assigning to your dropdowns, you could create a utility class that wraps a Queue as follows:

public class KVPCycle
{
   Queue<KeyValuePair<int, string>> queue; 

   public KVPCycle(IEnumerable<KeyValuePair<int, string>> items)
   {
       queue = new Queue<KeyValuePair<int, string>>(items);
   }

   public KeyValuePair<int, string> Next()
   {
    var item = queue.Dequeue();
    queue.Enqueue(item);
    return item;
   }

}

You can use it like this:

var cycle = new KVPCycle(d.OrderByDescending(kvp => kvp.Value));

// Loop over your dropdown lists
for each dropdown list

    var kvp = cycle.Next();

    // Get the key
    int key = kvp.Key;

    // Get the value
    string val = kvp.Value;

    // Now assign to your dropdown
    // ...

In this way, once you get to the end of your ordered list you'll automatically be back at the start again - the values rotate in a cycle.

Winston Smith
Confused. That would just be a collection sorted by the key and not the dictionary values.
Gabe
Although Gabe hasn't answered my direct question, my best guess is that he'd want to retrieve the keys but in an order based on their values.
Steven Sudit
@Steven You're correct, I had misread the question. Answer updated accordingly.
Winston Smith
Thank you Winston, that's kind of what I have now, but the issue is that there are more dropdowns (20-30) than keyvaluepairs (~10). After looping through all the keyvaluepairs once, I need to loop through them again (possibly 2 or more times) until all dropdowns have been assigned.I think the solution is to convert the dictionary to a List<DictionaryEntry> collection that's sorted by the value and use the index. That's what I'm working on now.
Gabe
@Gabe see updated answer.
Winston Smith
Brilliant, that's a lot more elegant and clean than what I was trying to do. That'll work nicely. Thank you so much!
Gabe
If all you want are the keys (as ordered by descending value), then all of this is overkill.
Steven Sudit
@Steven Indeed, it's a 1 liner - but the OP also seemed to be concerned with finding an elegant way of cycling through the values.
Winston Smith
If I understand correctly, though, he has no need for the values after their original use in sorting. That would mean that the `KVPCycle` class could be replaced with `Queue<string>`.
Steven Sudit
Not quite, because then he'd have to manage the cycling himself. It could of course, be replaced with `Cycle<T>` meaning it could be used to cycle objects of any type.
Winston Smith
You are correct. I was so focused on the sorting and return type that I missed the part about recycling values. Arguably, it might be more efficient to fill an array and keep an index that you use mod the size, but the implementation you gave would work reasonably well, and would require little testing or debugging. I would suggest that you change your example to use a generic and add a `Select(kvp => kvp.Key)` to the sorting expression. If you do this, I'll reward your correct answer with an upvote.
Steven Sudit