DuplicateDictionary - A dictionary-like class which allows duplicates
$begingroup$
Since I couldn't find any good answers I made my own class called DuplicateDictionary
for personal usage. I would like some tips to improve it.
public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{
}
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}
public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;
return false;
}
}
This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.
c# dictionary
$endgroup$
add a comment |
$begingroup$
Since I couldn't find any good answers I made my own class called DuplicateDictionary
for personal usage. I would like some tips to improve it.
public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{
}
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}
public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;
return false;
}
}
This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.
c# dictionary
$endgroup$
7
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49
add a comment |
$begingroup$
Since I couldn't find any good answers I made my own class called DuplicateDictionary
for personal usage. I would like some tips to improve it.
public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{
}
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}
public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;
return false;
}
}
This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.
c# dictionary
$endgroup$
Since I couldn't find any good answers I made my own class called DuplicateDictionary
for personal usage. I would like some tips to improve it.
public class DuplicateDictionary<TKey, TValue>: List<KeyValuePair<TKey, TValue>>
{
public DuplicateDictionary()
{
}
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
public DuplicateDictionary(Dictionary<TKey, TValue> dictionary)
{
foreach(KeyValuePair<TKey, TValue> kvp in dictionary)
{
this.Add(kvp);
}
}
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
public void Add(TKey key, TValue value)
{
this.Add(new KeyValuePair<TKey, TValue>(key, value));
}
public bool ContainsKey(TKey key)
{
foreach(KeyValuePair<TKey, TValue> kvp in this)
if(kvp.Key.Equals(key)) return true;
return false;
}
}
This class is useful for log things. I use it to log a calculator's past functions and numbers, and once equals is pressed, adds all the past numbers with the functions.
c# dictionary
c# dictionary
edited Aug 28 '15 at 3:47
hexagonest
asked Aug 27 '15 at 4:34
hexagonesthexagonest
15327
15327
7
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49
add a comment |
7
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49
7
7
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49
add a comment |
5 Answers
5
active
oldest
votes
$begingroup$
Such a data structure already exists, and is called ILookup<TKey, TElement>
. It can be created using the ToLookup
extension.
The
ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
method returns aLookup<TKey, TElement>
, a one-to-many dictionary that maps keys to collections of values. ALookup<TKey, TElement>
differs from aDictionary<TKey, TValue>
, which performs a one-to-one mapping of keys to single values.
var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}
// prints
// a - 1, 2, 3
// b - 4
// c - 5
As Vince pointed out, your DuplicateDictionary
will suffer from slow access. Lookup
won't.
$endgroup$
add a comment |
$begingroup$
First I second what Vince Panuccio stated in his answer
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.
Bug alert
This will break with an StackOverflowException
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
by calling this.ContainsKey()
which again refers to the Item
(this[TKey]
) property and if we would omit this call, it would just break again with a StackOverflowException
based on the return this[index];
which is reffering the property getter itself again.
Setting aside this big bug, an argument named index
usually indicates some kind of numerical type. So a better parameter name would be in this case just key
.
The ctor
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
could be easily improved by using the AddRange()
method of the List<T>
like so
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
this.AddRange(list);
}
but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue>
as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>>
like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
this.AddRange(items);
}
which can be called using a Dictionary
and a List
.
This looks good but we can still do better by using the ctor of the List
instead like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
: base(items)
{ }
$endgroup$
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
add a comment |
$begingroup$
It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.
What you have is a list of KeyValuePairs
which is not the same as a Dictionary
:-)
Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary
.
$endgroup$
add a comment |
$begingroup$
I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<>
to hold the values.
Here's an example:
public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
{
get
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
}
return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
}
set
{
foreach (var _value in value.Select(kvp => kvp.Value))
{
Add(key, _value);
}
}
}
public void Add(TKey key, TValue value)
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
values = new List<TValue>();
Add(key, values);
}
values.Add(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
{
foreach (var value in item.Value)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
}
}
}
static void Main(string args)
{
var dupDic = new DuplicateDictionary<string, string>();
dupDic.Add("abc", "123");
dupDic.Add("abc", "456");
dupDic.Add("xyz", "789");
dupDic.Add("xyz", "098");
dupDic.Add("xyz", "290");
foreach (var kvp in dupDic)
{
Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
}
Console.ReadKey();
}
$endgroup$
add a comment |
$begingroup$
You can List of KeyValuePair to store duplicates
Example :
List<KeyValuePair<string, string>> listKeyValPair= new List<KeyValuePair<string, string>>();
KeyValuePair<string, string> keyValue= new KeyValuePair<string, string>("KEY1", "VALUE1");
listKeyValPair.Add(keyValue);
New contributor
$endgroup$
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
return StackExchange.using("mathjaxEditing", function () {
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
});
});
}, "mathjax-editing");
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "196"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f102026%2fduplicatedictionary-a-dictionary-like-class-which-allows-duplicates%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
5 Answers
5
active
oldest
votes
5 Answers
5
active
oldest
votes
active
oldest
votes
active
oldest
votes
$begingroup$
Such a data structure already exists, and is called ILookup<TKey, TElement>
. It can be created using the ToLookup
extension.
The
ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
method returns aLookup<TKey, TElement>
, a one-to-many dictionary that maps keys to collections of values. ALookup<TKey, TElement>
differs from aDictionary<TKey, TValue>
, which performs a one-to-one mapping of keys to single values.
var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}
// prints
// a - 1, 2, 3
// b - 4
// c - 5
As Vince pointed out, your DuplicateDictionary
will suffer from slow access. Lookup
won't.
$endgroup$
add a comment |
$begingroup$
Such a data structure already exists, and is called ILookup<TKey, TElement>
. It can be created using the ToLookup
extension.
The
ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
method returns aLookup<TKey, TElement>
, a one-to-many dictionary that maps keys to collections of values. ALookup<TKey, TElement>
differs from aDictionary<TKey, TValue>
, which performs a one-to-one mapping of keys to single values.
var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}
// prints
// a - 1, 2, 3
// b - 4
// c - 5
As Vince pointed out, your DuplicateDictionary
will suffer from slow access. Lookup
won't.
$endgroup$
add a comment |
$begingroup$
Such a data structure already exists, and is called ILookup<TKey, TElement>
. It can be created using the ToLookup
extension.
The
ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
method returns aLookup<TKey, TElement>
, a one-to-many dictionary that maps keys to collections of values. ALookup<TKey, TElement>
differs from aDictionary<TKey, TValue>
, which performs a one-to-one mapping of keys to single values.
var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}
// prints
// a - 1, 2, 3
// b - 4
// c - 5
As Vince pointed out, your DuplicateDictionary
will suffer from slow access. Lookup
won't.
$endgroup$
Such a data structure already exists, and is called ILookup<TKey, TElement>
. It can be created using the ToLookup
extension.
The
ToLookup<TSource, TKey>(IEnumerable<TSource>, Func<TSource, TKey>)
method returns aLookup<TKey, TElement>
, a one-to-many dictionary that maps keys to collections of values. ALookup<TKey, TElement>
differs from aDictionary<TKey, TValue>
, which performs a one-to-one mapping of keys to single values.
var list = new List<Tuple<string, int>>
{
Tuple.Create("a", 1),
Tuple.Create("a", 2),
Tuple.Create("a", 3),
Tuple.Create("b", 4),
Tuple.Create("c", 5)
};
var lookup = list.ToLookup(t => t.Item1, t => t.Item2);
foreach(var kv in lookup)
{
Console.Write(kv.Key);
Console.WriteLine(" - " + string.Join(", ", kv));
}
// prints
// a - 1, 2, 3
// b - 4
// c - 5
As Vince pointed out, your DuplicateDictionary
will suffer from slow access. Lookup
won't.
answered Aug 27 '15 at 9:04
dcastrodcastro
1,057713
1,057713
add a comment |
add a comment |
$begingroup$
First I second what Vince Panuccio stated in his answer
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.
Bug alert
This will break with an StackOverflowException
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
by calling this.ContainsKey()
which again refers to the Item
(this[TKey]
) property and if we would omit this call, it would just break again with a StackOverflowException
based on the return this[index];
which is reffering the property getter itself again.
Setting aside this big bug, an argument named index
usually indicates some kind of numerical type. So a better parameter name would be in this case just key
.
The ctor
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
could be easily improved by using the AddRange()
method of the List<T>
like so
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
this.AddRange(list);
}
but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue>
as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>>
like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
this.AddRange(items);
}
which can be called using a Dictionary
and a List
.
This looks good but we can still do better by using the ctor of the List
instead like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
: base(items)
{ }
$endgroup$
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
add a comment |
$begingroup$
First I second what Vince Panuccio stated in his answer
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.
Bug alert
This will break with an StackOverflowException
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
by calling this.ContainsKey()
which again refers to the Item
(this[TKey]
) property and if we would omit this call, it would just break again with a StackOverflowException
based on the return this[index];
which is reffering the property getter itself again.
Setting aside this big bug, an argument named index
usually indicates some kind of numerical type. So a better parameter name would be in this case just key
.
The ctor
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
could be easily improved by using the AddRange()
method of the List<T>
like so
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
this.AddRange(list);
}
but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue>
as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>>
like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
this.AddRange(items);
}
which can be called using a Dictionary
and a List
.
This looks good but we can still do better by using the ctor of the List
instead like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
: base(items)
{ }
$endgroup$
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
add a comment |
$begingroup$
First I second what Vince Panuccio stated in his answer
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.
Bug alert
This will break with an StackOverflowException
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
by calling this.ContainsKey()
which again refers to the Item
(this[TKey]
) property and if we would omit this call, it would just break again with a StackOverflowException
based on the return this[index];
which is reffering the property getter itself again.
Setting aside this big bug, an argument named index
usually indicates some kind of numerical type. So a better parameter name would be in this case just key
.
The ctor
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
could be easily improved by using the AddRange()
method of the List<T>
like so
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
this.AddRange(list);
}
but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue>
as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>>
like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
this.AddRange(items);
}
which can be called using a Dictionary
and a List
.
This looks good but we can still do better by using the ctor of the List
instead like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
: base(items)
{ }
$endgroup$
First I second what Vince Panuccio stated in his answer
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary or with a set or list as its value.
Bug alert
This will break with an StackOverflowException
public TValue this[TKey index]
{
get
{
this.ContainsKey(index);
return this[index];
}
set
{
this[index] = value;
}
}
by calling this.ContainsKey()
which again refers to the Item
(this[TKey]
) property and if we would omit this call, it would just break again with a StackOverflowException
based on the return this[index];
which is reffering the property getter itself again.
Setting aside this big bug, an argument named index
usually indicates some kind of numerical type. So a better parameter name would be in this case just key
.
The ctor
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
foreach(KeyValuePair<TKey, TValue> kvp in list)
{
this.Add(kvp);
}
}
could be easily improved by using the AddRange()
method of the List<T>
like so
public DuplicateDictionary(List<KeyValuePair<TKey, TValue>> list)
{
this.AddRange(list);
}
but that isn't really needed in this way because you also have a ctor which takes an Dictionary<TKey, TValue>
as a parameter. I suggest to replace both ctors by a different one which only takes an IEnumerable<KeyValuePair<TKey, TValue>>
like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
{
this.AddRange(items);
}
which can be called using a Dictionary
and a List
.
This looks good but we can still do better by using the ctor of the List
instead like so
public DuplicateDictionary(IEnumerable<KeyValuePair<TKey, TValue>> items)
: base(items)
{ }
edited Apr 13 '17 at 12:40
Community♦
1
1
answered Aug 27 '15 at 4:59
HeslacherHeslacher
45.1k462158
45.1k462158
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
add a comment |
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
What does base do? Excuse my ignorance
$endgroup$
– hexagonest
Aug 27 '15 at 9:11
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
$begingroup$
Thats the calling of the ctor of the inherited class
$endgroup$
– Heslacher
Aug 27 '15 at 9:12
add a comment |
$begingroup$
It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.
What you have is a list of KeyValuePairs
which is not the same as a Dictionary
:-)
Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary
.
$endgroup$
add a comment |
$begingroup$
It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.
What you have is a list of KeyValuePairs
which is not the same as a Dictionary
:-)
Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary
.
$endgroup$
add a comment |
$begingroup$
It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.
What you have is a list of KeyValuePairs
which is not the same as a Dictionary
:-)
Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary
.
$endgroup$
It might help if you explain the problem you are trying to solve first, but I'll have a crack at this.
I don't think this class should have a reason to exist. A key is just that, a key. If you have duplicate keys and duplicate values what you're essentially after is a grouping or a dictionary with a set or list as its value.
What you have is a list of KeyValuePairs
which is not the same as a Dictionary
:-)
Dictionaries benefit from having unique keys by giving you fast lookups, I'm not sure what benefit you gain by having a DuplicateDictionary
.
edited Aug 28 '15 at 10:36
answered Aug 27 '15 at 4:44
Vince PanuccioVince Panuccio
33015
33015
add a comment |
add a comment |
$begingroup$
I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<>
to hold the values.
Here's an example:
public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
{
get
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
}
return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
}
set
{
foreach (var _value in value.Select(kvp => kvp.Value))
{
Add(key, _value);
}
}
}
public void Add(TKey key, TValue value)
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
values = new List<TValue>();
Add(key, values);
}
values.Add(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
{
foreach (var value in item.Value)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
}
}
}
static void Main(string args)
{
var dupDic = new DuplicateDictionary<string, string>();
dupDic.Add("abc", "123");
dupDic.Add("abc", "456");
dupDic.Add("xyz", "789");
dupDic.Add("xyz", "098");
dupDic.Add("xyz", "290");
foreach (var kvp in dupDic)
{
Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
}
Console.ReadKey();
}
$endgroup$
add a comment |
$begingroup$
I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<>
to hold the values.
Here's an example:
public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
{
get
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
}
return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
}
set
{
foreach (var _value in value.Select(kvp => kvp.Value))
{
Add(key, _value);
}
}
}
public void Add(TKey key, TValue value)
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
values = new List<TValue>();
Add(key, values);
}
values.Add(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
{
foreach (var value in item.Value)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
}
}
}
static void Main(string args)
{
var dupDic = new DuplicateDictionary<string, string>();
dupDic.Add("abc", "123");
dupDic.Add("abc", "456");
dupDic.Add("xyz", "789");
dupDic.Add("xyz", "098");
dupDic.Add("xyz", "290");
foreach (var kvp in dupDic)
{
Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
}
Console.ReadKey();
}
$endgroup$
add a comment |
$begingroup$
I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<>
to hold the values.
Here's an example:
public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
{
get
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
}
return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
}
set
{
foreach (var _value in value.Select(kvp => kvp.Value))
{
Add(key, _value);
}
}
}
public void Add(TKey key, TValue value)
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
values = new List<TValue>();
Add(key, values);
}
values.Add(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
{
foreach (var value in item.Value)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
}
}
}
static void Main(string args)
{
var dupDic = new DuplicateDictionary<string, string>();
dupDic.Add("abc", "123");
dupDic.Add("abc", "456");
dupDic.Add("xyz", "789");
dupDic.Add("xyz", "098");
dupDic.Add("xyz", "290");
foreach (var kvp in dupDic)
{
Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
}
Console.ReadKey();
}
$endgroup$
I think you want to have some kind of a multi value single key dictionary. So I suggest to use for example a List<>
to hold the values.
Here's an example:
public class DuplicateDictionary<TKey, TValue> : Dictionary<TKey, List<TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
public new IEnumerable<KeyValuePair<TKey, TValue>> this[TKey key]
{
get
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
return Enumerable.Empty<KeyValuePair<TKey, TValue>>();
}
return values.Select(v => new KeyValuePair<TKey, TValue>(key, v));
}
set
{
foreach (var _value in value.Select(kvp => kvp.Value))
{
Add(key, _value);
}
}
}
public void Add(TKey key, TValue value)
{
List<TValue> values;
if (!TryGetValue(key, out values))
{
values = new List<TValue>();
Add(key, values);
}
values.Add(value);
}
public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
{
foreach (var item in ((Dictionary<TKey, List<TValue>>)this))
{
foreach (var value in item.Value)
{
yield return new KeyValuePair<TKey, TValue>(item.Key, value);
}
}
}
}
static void Main(string args)
{
var dupDic = new DuplicateDictionary<string, string>();
dupDic.Add("abc", "123");
dupDic.Add("abc", "456");
dupDic.Add("xyz", "789");
dupDic.Add("xyz", "098");
dupDic.Add("xyz", "290");
foreach (var kvp in dupDic)
{
Console.WriteLine("Key = "{0}" Value = "{1}"", kvp.Key, kvp.Value);
}
Console.ReadKey();
}
edited Aug 27 '15 at 19:26
answered Aug 27 '15 at 18:52
t3chb0tt3chb0t
34.7k750121
34.7k750121
add a comment |
add a comment |
$begingroup$
You can List of KeyValuePair to store duplicates
Example :
List<KeyValuePair<string, string>> listKeyValPair= new List<KeyValuePair<string, string>>();
KeyValuePair<string, string> keyValue= new KeyValuePair<string, string>("KEY1", "VALUE1");
listKeyValPair.Add(keyValue);
New contributor
$endgroup$
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
add a comment |
$begingroup$
You can List of KeyValuePair to store duplicates
Example :
List<KeyValuePair<string, string>> listKeyValPair= new List<KeyValuePair<string, string>>();
KeyValuePair<string, string> keyValue= new KeyValuePair<string, string>("KEY1", "VALUE1");
listKeyValPair.Add(keyValue);
New contributor
$endgroup$
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
add a comment |
$begingroup$
You can List of KeyValuePair to store duplicates
Example :
List<KeyValuePair<string, string>> listKeyValPair= new List<KeyValuePair<string, string>>();
KeyValuePair<string, string> keyValue= new KeyValuePair<string, string>("KEY1", "VALUE1");
listKeyValPair.Add(keyValue);
New contributor
$endgroup$
You can List of KeyValuePair to store duplicates
Example :
List<KeyValuePair<string, string>> listKeyValPair= new List<KeyValuePair<string, string>>();
KeyValuePair<string, string> keyValue= new KeyValuePair<string, string>("KEY1", "VALUE1");
listKeyValPair.Add(keyValue);
New contributor
edited 8 mins ago
Sᴀᴍ Onᴇᴌᴀ
9,58362164
9,58362164
New contributor
answered 36 mins ago
Nagesh HugarNagesh Hugar
1
1
New contributor
New contributor
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
add a comment |
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
$begingroup$
Welcome to Code Review! Please read How do I write a good answer?: "Every answer must make at least one insightful observation about the code in the question." Please explain why your suggestion would be an improvement.
$endgroup$
– Sᴀᴍ Onᴇᴌᴀ
5 mins ago
add a comment |
Thanks for contributing an answer to Code Review Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
Use MathJax to format equations. MathJax reference.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f102026%2fduplicatedictionary-a-dictionary-like-class-which-allows-duplicates%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
7
$begingroup$
I think you should provide an example on how some1 is supposed to use this class. How are you going to access duplicate values? If you can't then why store them? Also your indexer looks really fishy.
$endgroup$
– Nikita B
Aug 27 '15 at 7:02
$begingroup$
Refer to the edit
$endgroup$
– hexagonest
Aug 28 '15 at 3:49