【问题标题】:Find closest value in a list in C# with linq?使用linq在C#中的列表中查找最接近的值?
【发布时间】:2014-11-12 15:44:20
【问题描述】:

我有一个这样的列表:

public List<Dictionary<int, int>> blanks { get; set; }

这会保留一些索引值:

此外,我还有一个名为 X 的变量。X 可以取任何值。我想找到最接近 X 的“键”值。例如:

如果 X 是 1300,我想取空白 index: 2 和 Key: 1200。 我怎样才能通过 linq 做到这一点?或者,有没有其他解决方案?

提前致谢。

编辑:如果它不是字典怎么办。如果是这样的 List 怎么办:

List&lt;List&lt;int[]&gt;&gt; lastList = new List&lt;List&lt;int[]&gt;&gt;();

这一次,我想取第一个 List 的索引和第二个 List 的索引。例如,如果 X 是 800,我想取 0 和 0(对于索引 0),还要取 1 和 1(对于索引 1)这次我该怎么办?

【问题讨论】:

  • 如果每个字典的计数为 1,为什么不使用键值对列表?

标签: c# linq dictionary indexing


【解决方案1】:
var diffs = blanks.SelectMany((item, index) => item.Select(entry => new
            { 
              ListIndex = index, // Index of the parent dictionary in the list 
              Key = entry.Key, // Key
              Diff = Math.Abs(entry.Key - X) // Diff between key and X
            }));

var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);

Dictionary<int, int> closestKeyDict = blanks[closestKey.ListIndex];
int closestKey = closestDiff.Key;
int closestKeyValue = closestKeyDict[closestKey];

SelectMany 子句将所有字典条目扁平化为 { ListIndex, DictionaryKey, Difference } 实例的集合。

然后聚合这个展平的集合以检索具有最小差异的项目。

回答你的第二个问题:

var diffs = blanks.SelectMany((list, listIndex) => list.
                   SelectMany((array, arrayIndex) => array.
                   Select((item, itemIndex) => new
                   { 
                     ListIndex = listIndex,
                     ArrayIndex = arrayIndex,
                     ItemIndex = itemIndex,
                     Diff = Math.Abs(item - X) 
                   })));

var closestDiff = diffs.Aggregate((agg, item) => (item.Diff < agg.Diff) ? item : agg);

现在在closestDiff 中,您将找到关闭项的索引(列表索引、数组索引和数组项索引)

【讨论】:

  • 为了得到一个最大值或最小值,每个人都痴迷于做一个完整的 O(n^2) OrderBy 是什么?
  • @Rawling 排序后的项目不仅包含差异,还包含列表索引+字典键
  • 您仍然不需要订购整个列表来查找最小值。
  • @Rawling,我已将其替换为聚合调用
  • @vc74 您在下面的解决方案运行良好: var diffs = kaynaklarArray[l].blanks.SelectMany((item, index) => item.Select(entry => new { Index = index, Key = entry.Key, Diff = Math.Abs​​(entry.Key - X) })).OrderBy(item => item.Diff); var mostDiff = diffs.First(); var key =最接近的Diff.Key; var value = (kaynaklarArray[l].blanks[closestDiff.Index])[closestDiff.Key];
【解决方案2】:

这可能不是最优化的方式,但应该可以正常工作,

List<Dictionary<int, int>> blanks = new List<Dictionary<int, int>>
{
    new Dictionary<int, int>{{100,200}},
    new Dictionary<int, int>{{500,200}},
    new Dictionary<int, int>{{700,200}},
    new Dictionary<int, int>{{1200,200}},
    new Dictionary<int, int>{{300,200}},
    new Dictionary<int, int>{{200,200}},
    new Dictionary<int, int>{{800,200}},
};

int x = 1300;

IEnumerable<int> keys = blanks.SelectMany(ints => ints.Keys);
var diff = keys.Select(i => Math.Abs(i - x)).ToList();
var index = diff.IndexOf(diff.Min());
var value = blanks[index].Keys.First();

【讨论】:

  • 这个解决方案也工作得很好而且很快。那么,如果它不是字典怎么办。如果是这样的 List 怎么办: List> blanks = new List>();有什么办法解决这个问题?
猜你喜欢
  • 2014-11-20
  • 1970-01-01
  • 2021-11-20
  • 2020-02-13
  • 2015-07-26
  • 2017-06-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多