C# 发现';下一个可用';输入字典或相关集合

C# 发现';下一个可用';输入字典或相关集合,c#,.net,linq,c#-4.0,collections,C#,.net,Linq,C# 4.0,Collections,我想编写一个linq扩展(或自定义字典、排序列表或任何最好的解决方案),允许我向集合添加一个值,其键为“下一个可用”键 例如: int CreatedKey = IncrementDictionary.AddNext(myCustomer); 如果当前存在的密钥如下所示: 1 2 8 4 3 然后它会将myCustomer添加到字典中,并使用5键返回该键 你觉得怎么样?我的解决方案比第一个短,但你可以从中得到一个想法 Dictionary<int, string>

我想编写一个linq扩展(或自定义字典、排序列表或任何最好的解决方案),允许我向集合添加一个值,其键为“下一个可用”键

例如:

int CreatedKey = IncrementDictionary.AddNext(myCustomer);
如果当前存在的密钥如下所示:

1
2
8
4
3
然后它会将myCustomer添加到字典中,并使用5键返回该键


你觉得怎么样?

我的解决方案比第一个短,但你可以从中得到一个想法

        Dictionary<int, string> x = new Dictionary<int, string>();
        x.Add(1, "a");
        x.Add(2, "a");
        x.Add(3, "a");
        x.Add(4, "a");
        x.Add(8, "a");
        Console.WriteLine((x.Keys.Where(k => !x.Keys.Contains(k + 1)).Min() + 1).ToString());
Dictionary x=newdictionary();
x、 添加(1,“a”);
x、 添加(2,“a”);
x、 添加(3,“a”);
x、 添加(4,“a”);
x、 添加(8,“a”);
Console.WriteLine((x.Keys.Where(k=>!x.Keys.Contains(k+1)).Min()+1.ToString());
公共静态int AddNext(本词典)
{
int min=dict.Keys.min();
int max=dict.Keys.max();
返回可枚举的.Range(min,max-min).Except(dict.Keys).First();
}
把它当作

int result = new Dictionary<int, string>(){ {1, "a"}, {2, "a"}, 
                                            {8, "a"}, {4, "a"}, 
                                                      {3, "a"}}.AddNext();
int result=newdictionary(){{1,“a”},{2,“a”},
{8,“a”},{4,“a”},
{3,“a”}}.AddNext();

这里的
结果是5。

您是否正在寻找类似的东西(它显然只能包含1000个元素)?可以有很多其他的解决方案,但很难说你到底想做什么。无论如何,这可能是一个起点

public class IncrementDictionary : Dictionary<int, object>
{
    private bool[] usedKeys = new bool[1000];

    public new void Add(int key, object value)
    {
        base.Add(key, value);
        usedKeys[key] = true;
    }

    public new void Clear()
    {
        base.Clear();
        usedKeys = new bool[1000];
    }

    public new object this[int key] 
    {
        get
        {
            return base[key];
        }
        set
        {
            base[key] = value;
            usedKeys[key] = true;
        }
    }

    public new bool Remove(int key)
    {
        usedKeys[key] = false;
        return base.Remove(key);
    }

    public int AddNext(object anObj)
    {
        int newKey = -1;
        for (int i = 1; i < 1000; i++)
            if (!usedKeys[i])
            {
                newKey = i;
                break;
            }
        if (newKey > 0)
            this.Add(newKey, anObj);
        return newKey;
    }
}
公共类增量字典:字典
{
私有bool[]usedKeys=新bool[1000];
public new void Add(int键,对象值)
{
添加(键、值);
usedKeys[键]=真;
}
公共新空白清除()
{
base.Clear();
usedKeys=新布尔值[1000];
}
公共新对象此[int key]
{
得到
{
返回基[键];
}
设置
{
基[键]=值;
usedKeys[键]=真;
}
}
公共新布尔删除(int键)
{
usedKeys[键]=假;
返回底座。移除(键);
}
公共int AddNext(对象anObj)
{
int newKey=-1;
对于(int i=1;i<1000;i++)
如果(!usedKeys[i])
{
newKey=i;
打破
}
如果(newKey>0)
添加(newKey,anObj);
返回newKey;
}
}
您可以使用扩展方法添加到下一个自动检索的密钥

假设数据结构是任何对象,带有数字键

以下是SortedList的扩展方法

public static class SortedListExtensions
{
    ///Add item to sortedList (numeric key) to next available key item, and return key
    public static int AddNext<T>(this SortedList<int, T> sortedList, T item)
    {
        int key = 1; // Make it 0 to start from Zero based index
        int count = sortedList.Count;

        int counter=0;
        do
        {
            if (count == 0) break;
            int nextKeyInList = sortedList.Keys[counter++];

            if (key != nextKeyInList) break;

            key = nextKeyInList +1;

            if (count == 1 || counter == count  ) break;


            if (key != sortedList.Keys[counter])
                break;

        } while (true);

        sortedList.Add(key, item);
        return key;
    }

}
您可以使用字典或任何其他数据结构。在这种情况下,将需要双回路。对于SortedList,搜索键时会保存一个循环。此循环由使用BinarySearch算法的函数在内部使用


二进制搜索比循环所有元素更快(对于较大的数据)。

好吧。。。这是个老问题,但我想回答

Nikhil Agrawal的代码可能会有所改进,因为如果您有一个空集合,则必须指定最小值。因此,代码变成:

 public static int FirstFree(Dictionary<int, Guid> dict, int minumum)
    {
        int min = dict.Count == 0
            ? minumum                       //use passed minimum if needed
            : dict.Keys.Min();              //use real minimum
        int max = dict.Count > 1
            ? dict.Keys.Max() + 2           //two steps away from maximum, avoids exceptions
            : min + 2;                      //emulate data presence
        return Enumerable.Range(min, max).Except(dict.Keys).First();
    }
publicstaticintfirstfree(Dictionary dict,intminumum)
{
int min=dict.Count==0
?最小值//如果需要,使用通过的最小值
:dict.Keys.Min();//使用实最小值
int max=指令计数>1
?dict.Keys.Max()+2//距离最大值两步,避免异常
:min+2;//模拟数据存在
返回可枚举的.Range(min,max).Except(dict.Keys).First();
}
但是,如果您在定义的范围内工作,您还应该知道是否有空间存储值。这可以是:

public static int? FirstFree(Dictionary<int, Guid> dict, int min, int max)
    {
        if (max <= min)
            throw new Exception($"Specified range is invalid (must be max > min)");
        if (max - min + 1 == dict.Count)
            //no space left
            return null;
        return Enumerable.Range(min, max).Except(dict.Keys).First();
    }
公共静态int?FirstFree(字典dict、int-min、int-max)
{

如果(max我想问题是什么还不清楚。我也不认为这会成为一个特别有用的数据结构,因为对象引用或哈希代码/相等方法的组合足以识别对象。嗨,威廉,看起来你的问题属于。你会在该网站上发现更好的响应率,因为它是我本来是想问这类问题的。@dtb但是OP要求人们评价(或回顾)他的想法,这里没有问题,他只是想问一个问题review@DoctaJonez:哪种想法?在我看来,这些问题似乎是OP在寻求满足其要求的代码。@dtb它的内容是“我在做什么,你怎么看?”.听起来像是一个你熟悉的复习问题?@dtb是的;)谢谢你的帮助:)虽然我的答案真的很好:)哇+1对你来说NikHil:)你用一行击中了答案:)另一个伟大的@dtb例子:我知道,但这在这里是怎么应用的?你能吗explain@dtb为什么你总是说不管是谁,施莱米尔:)他是你的大学教授吗?你在字典里插入的每一个键,你都必须在查找下一个密钥时需要多做一些工作。这是非常低效的。应该使用适当的数据结构来解决问题,而不是使用暴力。
        1 a
        2 b
        3 c
        4 BCD
        5 d
        6 BCD
        7 e
 public static int FirstFree(Dictionary<int, Guid> dict, int minumum)
    {
        int min = dict.Count == 0
            ? minumum                       //use passed minimum if needed
            : dict.Keys.Min();              //use real minimum
        int max = dict.Count > 1
            ? dict.Keys.Max() + 2           //two steps away from maximum, avoids exceptions
            : min + 2;                      //emulate data presence
        return Enumerable.Range(min, max).Except(dict.Keys).First();
    }
public static int? FirstFree(Dictionary<int, Guid> dict, int min, int max)
    {
        if (max <= min)
            throw new Exception($"Specified range is invalid (must be max > min)");
        if (max - min + 1 == dict.Count)
            //no space left
            return null;
        return Enumerable.Range(min, max).Except(dict.Keys).First();
    }
public static int FirstFree(Dictionary<int, Guid> dict, int min, int max)
    {
        if (max <= min)
            throw new Exception($"Specified range is invalid (must be max > min)");
        if (max - min + 1 == dict.Count)
            //no space left
            return int.MinValue;
        return Enumerable.Range(min, max).Except(dict.Keys).First();
    }