Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/329.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/10.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# 我可以从已排序的IEnumerable创建字典而不必使用?_C#_Algorithm_Linq_Optimization - Fatal编程技术网

C# 我可以从已排序的IEnumerable创建字典而不必使用?

C# 我可以从已排序的IEnumerable创建字典而不必使用?,c#,algorithm,linq,optimization,C#,Algorithm,Linq,Optimization,在C中,假设我有一个IEnumerable 它是按其int元素排序的。我想从中进行Olog n查找,并且确保我可以使用System.Linq这样做 var lookups = alreadySorted.ToDictionary(x => x.Item1, x => x.Item2); foreach(var i in someArray) someMethod(lookups.Find(i)); 但这有一个缺点:在制作字典时,它必须再次对已排序的IEnumerable进行排序,因

在C中,假设我有一个IEnumerable 它是按其int元素排序的。我想从中进行Olog n查找,并且确保我可以使用System.Linq这样做

var lookups = alreadySorted.ToDictionary(x => x.Item1, x => x.Item2);
foreach(var i in someArray) someMethod(lookups.Find(i));
但这有一个缺点:在制作字典时,它必须再次对已排序的IEnumerable进行排序,因为它无法知道我已经对它进行了排序。有什么合理的方法可以解决这个问题吗

编辑:我被告知Dictionary不是用于传统的二进制搜索,而是用于hashmapping,所以这个示例应该使用System.Collections.Generic.SortedSet,而不是

如果您的目标是获得Olog n查找并避免任何进一步的排序,那么应该使用ToList而不是ToDictionary


然后,您将与仅对元组的项1进行比较的自定义IComparer一起使用。

作为不信者Damien_答案的延续,我在实用程序类中定义了以下方法,因此我不必为IComparer创建新类:

   public static Tuple<int, int> IndexesOf<Et, Ct>(this IList<Et> haystack, Ct needle, Func<Et, Ct, int> func)
    {
        int minStart = 0;
        int maxStart = haystack.Count();
        int minEnd = 0;
        int maxEnd = haystack.Count();
        while(minStart != maxStart)
        {
            int i = (minStart + maxStart) / 2;
            var direction = func(haystack[i], needle);
            if (direction < 0)
            {
                minStart = i+1;
                minEnd = i+1 < minEnd? minEnd: i+1;
            }
            else if (direction == 0)
            {
                maxStart = i;
                minEnd = i+1 < minEnd ? minEnd : i + 1;
            }
            else
            {
                maxStart = i;
                maxEnd = i;
            }
        }

        while (minEnd != maxEnd)
        {
            int i = (minEnd + maxEnd) / 2;
            var direction = func(haystack[i], needle);
            if (direction <= 0) minEnd = i+1;
            else maxEnd = i;
        }

        return Tuple.Create(minStart, minEnd);
    }

当然,查找所有匹配项的索引范围而不是一个匹配项的索引有些浪费。

如果您将查找字段设置为SortedList类型,可能可以避免重新排序。Dictionary使用哈希实现接近O1的查找,但这样做肯定不保序。而bare IEnumerable不提供随机访问,所以你不能在上面实现二进制搜索,这可能是你在说Olog n.SortedList时想到的?从来没有听说过这样的,我以为有一个排序集重新组合一个排序列表。但我不知道如何在不使用IEnumerable的情况下创建IEnumerable的集合。@dukc-但问题是,字典不会对项目进行排序-它会对项目进行散列,并使用散列进行访问。所以对枚举进行预排序没有任何好处,因为这些项在字典中的顺序不正确。这就是我要寻找的。我是否可以不借助任何工具将其转换为SortedSet?不需要,但可能会有帮助。为什么你这么关心重新排序@dukc?这会浪费计算能力。好的,我承认我没有做任何性能关键的东西,我负担不起,但更快总是更好。更快并不总是更好,有时可读性和可维护性更重要。事实上,我甚至可以说,除非性能确实导致了问题,否则它在该列表中排名第三。
foreach(var i in someArray)
{   someMethod(lookups[lookups.IndexesOf(i, (a, b) => a.Item1 - b).Item1]);
}