Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/ms-access/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
修改字典(C#)条目上的重复键值_C#_Dictionary - Fatal编程技术网

修改字典(C#)条目上的重复键值

修改字典(C#)条目上的重复键值,c#,dictionary,C#,Dictionary,我需要使用字典来存储“key=value”对,但是现在我需要存储“replicate”键值 我有一行带分隔符的文本(用管道字符(“|”)分隔),我将其拆分为一个数组,然后再拆分为一个字典(见下文) 如果不存在重复项,这可以正常工作,但我希望以一种在插入前调整键值的方式存储重复的键 范例 A=1|B=2|C=3|D=4|D=5|D=5 我希望将键值调整为以下值: A=1 B=2 C=3 D=4 D[1]=5 D[2]=5 然后我可以取出第二个和第三个“D”项的条目,因为它们有一个新的键值 每个

我需要使用字典来存储“key=value”对,但是现在我需要存储“replicate”键值

我有一行带分隔符的文本(用管道字符(“|”)分隔),我将其拆分为一个数组,然后再拆分为一个字典(见下文)

如果不存在重复项,这可以正常工作,但我希望以一种在插入前调整键值的方式存储重复的键

范例

A=1|B=2|C=3|D=4|D=5|D=5
我希望将键值调整为以下值:

A=1
B=2
C=3
D=4
D[1]=5
D[2]=5
然后我可以取出第二个和第三个“D”项的条目,因为它们有一个新的键值

每个副本都是一个unqiue记录,因此我希望能够按照输入的顺序进行引用。例如,第四个条目将是D[4]。关于对所有值使用相同键值的建议可能会/将令人困惑,并且我可能最终提取错误的信息(但请记住)

我希望避免事先遍历数组,并想知道是否有人知道我可以在上面代码的ToDictionary部分执行此操作的方法

为这相当基本的解释道歉。
许多线程处理删除字典中的重复项,我知道这不是字典的预期用途。

如果要将多个值与一个键关联,可以将该对的值部分设置为一个列表:

var dict = new Dictionary<char, List<int>>();

char key = 'D';
int value = 5;

if (!dict.ContainsKey(key))
    dict[key] = new List<int>();
dict[key].Add(value);
var dict=newdictionary();
字符键='D';
int值=5;
如果(!dict.ContainsKey(键))
dict[key]=新列表();
dict[键]。添加(值);

您可以使用具有基于集合的值的词典:

Dictionary<string, List<int>>
字典
然后,您可以为所需的作业使用最佳的数据结构,但是
List
是一个很好的默认值

或者您可以使用
Lookup
类,但这不会为值元素提供数组索引:

Lookup<string, int>
查找
它支持键下的分组(因此可枚举的
TElement



或者,也可以滚动您自己的数据结构,但这不太可能是必需的-现有内容的组合可能会对您足够好。

您可以使用
GroupBy
按键对结果集进行分组,然后使用
SelectMany展平分组,使用
S投影所需的键选择带有索引参数的方法重载:

var message = t
    .Select(s => s.Split('='))
    .GroupBy(s => s[0], s => s[1])
    .SelectMany(g => g.Select((v, i) => new
    {
        Key = i == 0 ? g.Key : g.Key + "[" + i + "]",
        Value = v
    }))
    .ToDictionary(e => e.Key, e => e.Value);

嗯..我将给出一个基本答案,不使用LINQ。我要做的是创建自己的
ToDictionary
方法,只需检查一个键是否存在,如果存在,则创建新键并将其添加到
字典中,类似这样:

public Dictionary<string,string> ToDictionary(string[] t)
{
    Dictionary<string, string> dict = new Dictionary<string, string>();
    foreach (string s in t)
    {
        string[] reg = s.Split('=');
        int i = 1;
        while (dict.ContainsKey(reg[0]))
        {
            if (!reg[0].Contains('['))
                reg[0] = reg[0] + "[" + i.ToString() + "]";
            else
                reg[0] = reg[0].Replace((i - 1).ToString(), i.ToString());
            i++;
        }

        dict.Add(reg[0], reg[1]);
    }
    return dict;
}
公共字典目录(字符串[]t)
{
Dictionary dict=新字典();
foreach(t中的字符串s)
{
字符串[]reg=s.Split('=');
int i=1;
while(dict.ContainsKey(reg[0]))
{
如果(!reg[0]。包含('['))
reg[0]=reg[0]+“[”+i.ToString()+“]”;
其他的
reg[0]=reg[0]。替换((i-1).ToString(),i.ToString());
i++;
}
dict.Add(reg[0],reg[1]);
}
返回命令;
}

这可以很容易地用扩展方法进行转换。

就像Adam Houldsworth说的那样,您可以使用
查找

下面是一个基于亚当·霍尔德斯沃思答案的片段

var str = @"A=1|B=2|C=3|D=4|D=5|D=5";
string[] t = str.Split(new[] { '|', '|' }, StringSplitOptions.RemoveEmptyEntries);
var message = t.ToLookup(s => s.Split('=')[0], s => Convert.ToInt32(s.Split('=')[1]));
var res = message.ToDictionary(i=>i.Key, x=>x.LastOrDefault());
编辑:

在再次阅读您的问题后,我理解您也需要D=4的值

var res = message.SelectMany(i => i.Select((x, y) => new
{
    Key = i.Key,
    Value = x
})).GroupBy(q=>q.Value)
   .SelectMany(x=>x.ToLookup(xx=>xx.Key, xx=>xx.Value));

另一种方法是在System.Collections.Specialized中使用NameValueCollection。NameValueCollection的有趣之处在于,如果同一个键有重复的值,它会将这些值保留在同一个键中,作为逗号分隔的值。这样键将是相同的,但这些值可能必须将其分隔开。 下面给出了一个快速示例和输出

class Program
{
    static void Main(string[] args)
    {
        NameValueCollection col = new NameValueCollection();
        col.Add("A", "1");
        col.Add("A", "2");
        col.Add("B", "0");
        col.Add("B", "1");
        col.Add("B", "3");
        col.Add("D", "1");
        foreach (string key in col.AllKeys)
        {
            Console.WriteLine(key + " " + col[key] + "\n");
        }
        Console.ReadKey();
    }
}
输出 A 1,2 b0,1,2 D 1

您必须设计自己的数据结构来跟踪重复项。或者按照@itsme86所说的去做。但这取决于您希望如何检索这些信息。词典的使用者如何知道他们想要第一个
D
键还是第二个?Quantic-第一个条目是D,第二个是D[1],第三个是D[2]以此类推,“[]”的格式就是唯一地插入密钥。然后他们会输入他们想看到的密钥。这听起来是一个很好的解决方案。以前做过很多次。谢谢你的评论。问题是每个重复的密钥都是一个单独的记录,所以将它们聚在一起意味着我将失去根据unqiue值提取数据的能力。我将更详细地更新这个问题。@Arclight我不确定我是否理解。你可以只做
dict['D'][1]
获取第二个D条目。@Fabio很公平。我将把它留给您的评论来添加-OP除了能够按照插入顺序索引之外,实际上并没有太多关于用法的说明,而
Lookup
实际上并没有提供任何一种方法,但我感觉这是一个XY问题。
class Program
{
    static void Main(string[] args)
    {
        NameValueCollection col = new NameValueCollection();
        col.Add("A", "1");
        col.Add("A", "2");
        col.Add("B", "0");
        col.Add("B", "1");
        col.Add("B", "3");
        col.Add("D", "1");
        foreach (string key in col.AllKeys)
        {
            Console.WriteLine(key + " " + col[key] + "\n");
        }
        Console.ReadKey();
    }
}