views:

96

answers:

3

Hi,

I have a Dictionary object that is formed using a double as its key values. It looks like this:

Dictionary<double, ClassName> VariableName = new Dictionary<double, ClassName>();

For my project I have to have the key as the double as I require values like 1.1,1.2,2.1,2.2,etc in my system.

Everything in my system works great except when I want to delete all the keys in a group eg all the 1 values would be 1.1,1.2, etc.

I can delete rows if I know the full value of the key eg 1.1 but in my system I will only know the whole number.

I tried to do the following but get an error:

DictionaryVariable.Remove(j => Convert.ToInt16(j.Key) == rowToEdit).OrderByDescending(j => j.Key);

Is there anyway to remove all rows per int value by converting the key?

Thanks, Rich

+4  A: 

First, consider using Decimal instead of Double. Double is floating-point and it is not appropriate for exact comparisons (which is essential for key-value lookups). You would still be able to handle numbers such as 1.1 or 2.2.

Second, what you need is:

dictionary.Remove(rowToEdit); // where rowToEdit is the
                              // key of the key-value par you want
                              // to remove

EDIT: To remove values where rowToEdit is an integer and you want remove everthing where rowToEdit <= k < (rowToEdit + 1)

var removedKeys = x.Keys
    .Where(k => k >= 0 ? Math.Floor(k) : Math.Ceiling(k) == rowToEdit).ToArray();
foreach (var key in removedKeys) dictionary.Remove(key);
DrJokepu
He's asking to remove dictionary entries with keys 1.1, 1.2, 1.3, etc. when rowToEdit is 1 (for example).
Jamie Ide
Jamie's answer works fine for doubles, so although I agree that Decimals are usually safer than Doubles, it's not really relevant to this question.
ho1
@ho: It's a preemptive general advice. If he uses floating-point arithmetic to find the keys of rows he will run into hard-to-debug bugs.
DrJokepu
+1: Especially for first statement.
Binary Worrier
Can't you just use `RemoveAll` instead of a `foreach`?
James
@James: Dictonary<T> does not expose such a method unfortunately.
DrJokepu
While I agree with DrJokepu's approach, couldn't you also just cast the double as an int? According to the documentation, casting double as int just truncates it. I don't know LINQ or if this would work, but I would hazard to try something like `Where(k => (int)k == rowToEdit)`.
ccomet
@ccomet: That would work as well, however, it would have the same bug as I had in my previous example; it wouldn't work correctly for negative values of k. Hence my change to Math.Floor() and Math.Ceiling()
DrJokepu
@DrJokepu, Ah I was assuming instead of using the `Where` you could directly replace this with `RemoveAll` (LINQ). However, you could wrap up your `foreach` into an Extension method of Dictionary. Would be a handy utility :)
James
@DrJokepu Hah, I didn't notice the Math.Floor() or Math.Ceiling() until now. Given the style of the dictionary I wouldn't expect negative values but sometimes it is better to have more universally operational code.
ccomet
+4  A: 

Try this:

var filter = dictionary.Where(x => x.Key - rowToEdit < 1).ToArray();
foreach (var pair in filter)
{
    dictionary.Remove(pair.Key);
}
Jamie Ide
Why would you call `ToArray()` on that? That will just cause the data to copied into an array for no reason, especially since the next line immediately is a ForEach which would cause the enumerable from above to evaluate itself anyway?
Chris Marisic
The filter has to be copied into another container because otherwise it is a reference to the dictionary entry and an InvalidOperationException is thrown ("Collection was modified; enumeration operation may not execute.") because the collection is changed in the loop when items are removed. I know because I initially wrote the test case without ToArray(). :-)
Jamie Ide
Thanks very much for that. It worked a treat :) I've also changed to use Decimals as well as per @DrJokepu suggestion.
Richard Reddy
For anyone who comes across this later, just a warning that this wouldn't always work for negative numbers ([-2.3] - [1] = -3.3 < 1). This shouldn't affect the OP's choice for accepting the answer, but just as a note to watch out for.
ccomet
For my case there will only ever be positive numbers created for the keys but thanks for the heads up. Not sure why you'd want a dictionary object with negative keys anyways but that's prob another question ;)
Richard Reddy
A: 

You can use LINQ:

var itemsToDelete = from key in dictionary.Keys where ((int)key).Equals(intValueToDelete) select key;
foreach (var keyToDelete in itemsToDelete)
{
    dictionary.Remove(value);
}
Daniel Rose