Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/304.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/8/linq/3.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#_Linq_Dictionary - Fatal编程技术网

C# 在字典中查找差异最小的键

C# 在字典中查找差异最小的键,c#,linq,dictionary,C#,Linq,Dictionary,说吧,我有这个收藏,它是通用字典 var items = new Dictionary<int, SomeData> { { 1 , new SomeData() }, { 5 , new SomeData() }, { 23 , new SomeData() }, { 22 , new SomeData() }, { 2 , new SomeData() }, { 7 , new SomeData() }, { 59

说吧,我有这个收藏,它是通用字典

var items = new Dictionary<int, SomeData>
{
    { 1  , new SomeData() },
    { 5  , new SomeData() },
    { 23 , new SomeData() },
    { 22 , new SomeData() },
    { 2  , new SomeData() },
    { 7  , new SomeData() },
    { 59 , new SomeData() }
}
var allPair = items.SelectMany((l) => items.Select((r) => new {l,r}).Where((pair) => l.Key != r.Key));
问题:如何在通用字典中找到键之间的最小差异?是否有一种LINQ解决方案


目的:如果有多个匹配项,那么我只需要一个匹配项-最小的,这是用来填补项目之间缺少的关键点(间隙)

不确定Linq是否最合适,但是(大致)这方面应该可以做到:

var smallestDiff = (from key1 in items.Keys
                    from key2 in items.Keys
                    where key1 != key2
                    group new { key1, key2 } by Math.Abs (key1 - key2) into grp
                    orderby grp.Key
                    from keyPair in grp
                    orderby keyPair.key1
                    select keyPair).FirstOrDefault ();

我不知道如何在LINQ中一行完成,但这是解决这个问题的多行解决方案

         var items = new Dictionary<int, string>();
         items.Add(1, "SomeData");
         items.Add(5, "SomeData");
         items.Add(23, "SomeData");
         items.Add(22, "SomeData");
         items.Add(2, "SomeData");
         items.Add(7, "SomeData");
         items.Add(59, "SomeData"); 

         var sortedArray = items.Keys.OrderBy(x => x).ToArray();

         int minDistance = int.MaxValue;

         for (int i = 1; i < sortedArray.Length; i++)
         {
             var distance = Math.Abs(sortedArray[i] - sortedArray[i - 1]);
             if (distance < minDistance)
                 minDistance = distance;
         }

         Console.WriteLine(minDistance);
var items=newdictionary();
增加(1,“某些数据”);
增加(5,“某些数据”);
增加(23,“某些数据”);
增加(22,“某些数据”);
增加(2,“某些数据”);
增加(7,“某些数据”);
增加(59,“某些数据”);
var sortedArray=items.Keys.OrderBy(x=>x.ToArray();
int minDistance=int.MaxValue;
for(int i=1;i
我不会给你LinQ查询,因为已经有答案了。 我知道这不是您所要求的,但如果性能和易读性是您关心的问题,我想向您展示如何以非常快速和易于理解/维护的方式解决它

int[] keys;
int i, d, min;

keys = items.Keys.ToArray();
Array.Sort(keys); // leverage fastest possible implementation of sort

min = int.MaxValue;
for (i = 0; i < keys.Length - 1; i++)
{
  d = keys[i + 1] - key[i]; // d is always non-negative after sort
  if (d < min)
  {
    if (d == 2)
    {
      return 2; // minimum 1-gap already reached
    } else if (d > 2) // ignore non-gap
    {
      min = d;
    }
  }
}

return min; // min contains the minimum difference between keys
这意味着什么

假设具有1-gap的概率很高,如果您已达到该最小gap,则每次更改
min
时检查可能会更快。这可能发生在您通过for循环的概率为1%或10%时。因此,对于非常大的集合(例如,超过100万或10亿),一旦您知道预期的概率,这种概率方法可能会给您带来巨大的性能收益

相反,对于较小的集或1-gap的概率较低时,这些额外的CPU周期会被浪费,如果不进行检查,情况会更好

与非常大的数据库(考虑概率索引)一样,概率推理也变得相关

问题是,你必须事先估计概率效应是否以及何时起作用,这是一个相当复杂的话题

编辑2:1-gap的索引差实际上为
2
。此外,
1
的索引差是一个非间隙(在两者之间没有插入索引的间隙)

因此,前面的解决方案完全是错误的,因为一旦两个索引是连续的(比如34,35),最小值将是
1
,这根本不是一个间隙


由于这个间隙问题,内部
if()
是必要的,此时概率方法的开销为零。使用正确的代码和概率的方法会更好

我认为LINQ是最简单的

首先,从你的字典中找出差异对

var items = new Dictionary<int, SomeData>
{
    { 1  , new SomeData() },
    { 5  , new SomeData() },
    { 23 , new SomeData() },
    { 22 , new SomeData() },
    { 2  , new SomeData() },
    { 7  , new SomeData() },
    { 59 , new SomeData() }
}
var allPair = items.SelectMany((l) => items.Select((r) => new {l,r}).Where((pair) => l.Key != r.Key));
然后求微分的最小值

allPair.OrderBy((pair) => Math.Abs(pair.l.Key - pair.r.Key)).FirstOrDefault();

但您可能有多个具有相同差值的对,因此您可能需要在使用OrderBy之前使用GroupBy,然后自己处理多个对,答案中未列出一行解决方案:

items.Keys.OrderBy(x => x).Select(x => new { CurVal = x, MinDist = int.MaxValue }).Aggregate((ag, x) => new { CurVal = x.CurVal, MinDist = Math.Min(ag.MinDist, x.CurVal - ag.CurVal) }).MinDist

这闻起来像是一种味道。为什么需要计算关键点之间的最小值?当有超过一分钟的比赛时,你会期望发生什么?@YuvalItzchakov:更新的有目的的问题Linq并不总是所有问题的答案。试着编写一个函数来实现这一点-这可能比你想象的要简单。顺便说一句,你可以使用实际的字典初始值设定项,而不是不会编译的
x=>y
。@Matíasfidemrazizer:提到的集合是一个伪代码,我说这是一个字典只是为了简单,我知道如何在.NETThanks中实例化泛型集合,尽管这将是一个相当大的集合,因此我不想重复它,不幸的是,这个示例包含了太多的泛型集合,这正是我认为Linq不合适的原因;)@阿姆:嗯,对于那些熟悉LINQ的人来说,它看起来确实足够简单和简洁,尽管在这种特殊情况下,就性能而言,最好还是使用commonloop@Andy顺便说一句,性能考虑是相对于您的具体用例中的实际性能影响…您应该添加低指数(i-1)或者可以使用一个数组来保留所选密钥对的位置(或直接值),以防出现多个匹配被否决的情况,但Oleg的答案是第一个,因此,所有的信用都归他所有。没关系,你可以自由决定谁投赞成票或反对票,或者应用什么道德推理。尽管如此,请看我所做的编辑,它可能与您相关:)我喜欢您关于最小间隙的想法,一般来说,它肯定会提高性能,但在我的例子中,日期作为键的格式为“纪元后秒”,unix时间戳,它们之间的最小步长可能会有所不同,例如,如果字典中的项为小时,则最近键之间的最小步长应等于3600秒(1小时),如果项为天,则最小步长为86400秒(1天),依此类推。。。