使用 LINQ 从 C# 泛型字典中查询值
Query values from a C# Generic Dictionary using LINQ
这是我的代码:
Dictionary<double, long> dictionary = new Dictionary<double, long>();
dictionary.Add(99, 500);
dictionary.Add(98, 500);
dictionary.Add(101, 8000);
dictionary.Add(103, 6000);
dictionary.Add(104, 5);
dictionary.Add(105, 2000);
double price = 100;
我想要的查询是:
最接近价格且具有最低值的键。
所以在上面的例子中它应该是 return 99。
我如何在 LINQ 中对此进行编码?
我看过很多 linq 示例,但我无法根据自己的需要调整其中任何一个 b/c 我的查询有 2 个条件。
感谢您的帮助。
编辑:
根据@nintendojunkie 和@DmitryMartovoi 的评论,我不得不重新考虑我的方法。
如果我优先考虑最接近价格的键,那么结果值可能不是最低的,如果我首先优先考虑值,那么键可能离价格太远,所以查询必须优先考虑键和值,并给我最低的值用最接近价格的钥匙。 key 和 value 同样重要。
有人可以帮忙吗?
谢谢
你可以这样做:
var result = dictionary.Select(c => new { c.Key, Diff = Math.Abs(price - c.Key) + Math.Abs(price - c.Value), c.Value }).OrderBy(c => c.Diff).FirstOrDefault();
var price = 100.0;
var nearestKey = (from pair in dictionary
let diff = Math.Abs(pair.Key - price)
select new {Key = pair.Key, Diff = diff}
order by diff desc).First().Key;
var minValue = dictionary[nearestKey];
也许你想要一个神奇的 linq 查询,但我建议试试下面的查询。
public static class MyExtensions
{
public static double? GetNearestValue (this IDictionary<double, long> dictionary, double value)
{
if (dictionary == null || dictionary.Count == 0)
return null;
double? nearestDiffValue = null;
double? nearestValue = null;
foreach (var item in dictionary) {
double currentDiff = Math.Abs (item.Key - value);
if (nearestDiffValue == null || currentDiff < nearestDiffValue.Value) {
nearestDiffValue = currentDiff;
nearestValue = item.Value;
}
}
return nearestValue;
}
}
然后这样调用
Console.WriteLine (dictionary.GetNearestValue (100d));
var min = dictionary
.OrderBy(pair => pair.Value)
.Select(pair =>
new
{
k = pair.Key,
d = Math.Abs(pair.Key - price)
})
.OrderBy(t => t.d)
.Select(t => t.k)
.FirstOrDefault();
别忘了——你用的是字典。字典只有唯一的键。我想你认为这个结构是 List<KeyValuePair<double, long>>
。如果是这样 - 请看这个例子:
var minimumKeyDifference = dictionary.Min(y => Math.Abs(y.Key - price));
var minimumItems = dictionary.Where(x => Math.Abs(x.Key - price).Equals(minimumKeyDifference));
var desiredKey = dictionary.First(x => x.Value.Equals(minimumItems.Where(y => y.Key.Equals(x.Key)).Min(y => y.Value))).Key;
如果您将字典键的数据类型更改为 decimal
而不是 double
,则以下内容有效。
decimal price = 100;
decimal smallestDiff = dictionary.Keys.Min(n => Math.Abs(n - price));
var nearest = dictionary.Where(n => Math.Abs(n.Key - price) == smallestDiff)
.OrderBy(n => n.Value).First();
如果您使用 double
,这可能会由于四舍五入问题而失败,但是 decimal
是与金钱有关的任何事情的首选,以避免这些问题。
你说你需要找到最接近的价格和最低的值,但你没有定义两者之间的优先级分配规则。在下面,我赋予它们相同的优先级:1 的价格距离相当于 1 的值。
var closest =
dictionary.OrderBy(kvp => Math.Abs(kvp.Key - price) + kvp.Value).First();
为了性能,OrderBy(…).First()
应替换为 MinBy(…)
运算符(如果可用)。
编辑:如果该值仅用作决胜局,则使用此(也由 发布):
var closest =
dictionary.OrderBy(kvp => Math.Abs(kvp.Key - price))
.ThenBy(kvp => kvp.Value)
.First();
这是我的代码:
Dictionary<double, long> dictionary = new Dictionary<double, long>();
dictionary.Add(99, 500);
dictionary.Add(98, 500);
dictionary.Add(101, 8000);
dictionary.Add(103, 6000);
dictionary.Add(104, 5);
dictionary.Add(105, 2000);
double price = 100;
我想要的查询是: 最接近价格且具有最低值的键。 所以在上面的例子中它应该是 return 99。 我如何在 LINQ 中对此进行编码? 我看过很多 linq 示例,但我无法根据自己的需要调整其中任何一个 b/c 我的查询有 2 个条件。
感谢您的帮助。
编辑: 根据@nintendojunkie 和@DmitryMartovoi 的评论,我不得不重新考虑我的方法。 如果我优先考虑最接近价格的键,那么结果值可能不是最低的,如果我首先优先考虑值,那么键可能离价格太远,所以查询必须优先考虑键和值,并给我最低的值用最接近价格的钥匙。 key 和 value 同样重要。 有人可以帮忙吗? 谢谢
你可以这样做:
var result = dictionary.Select(c => new { c.Key, Diff = Math.Abs(price - c.Key) + Math.Abs(price - c.Value), c.Value }).OrderBy(c => c.Diff).FirstOrDefault();
var price = 100.0;
var nearestKey = (from pair in dictionary
let diff = Math.Abs(pair.Key - price)
select new {Key = pair.Key, Diff = diff}
order by diff desc).First().Key;
var minValue = dictionary[nearestKey];
也许你想要一个神奇的 linq 查询,但我建议试试下面的查询。
public static class MyExtensions
{
public static double? GetNearestValue (this IDictionary<double, long> dictionary, double value)
{
if (dictionary == null || dictionary.Count == 0)
return null;
double? nearestDiffValue = null;
double? nearestValue = null;
foreach (var item in dictionary) {
double currentDiff = Math.Abs (item.Key - value);
if (nearestDiffValue == null || currentDiff < nearestDiffValue.Value) {
nearestDiffValue = currentDiff;
nearestValue = item.Value;
}
}
return nearestValue;
}
}
然后这样调用
Console.WriteLine (dictionary.GetNearestValue (100d));
var min = dictionary
.OrderBy(pair => pair.Value)
.Select(pair =>
new
{
k = pair.Key,
d = Math.Abs(pair.Key - price)
})
.OrderBy(t => t.d)
.Select(t => t.k)
.FirstOrDefault();
别忘了——你用的是字典。字典只有唯一的键。我想你认为这个结构是 List<KeyValuePair<double, long>>
。如果是这样 - 请看这个例子:
var minimumKeyDifference = dictionary.Min(y => Math.Abs(y.Key - price));
var minimumItems = dictionary.Where(x => Math.Abs(x.Key - price).Equals(minimumKeyDifference));
var desiredKey = dictionary.First(x => x.Value.Equals(minimumItems.Where(y => y.Key.Equals(x.Key)).Min(y => y.Value))).Key;
如果您将字典键的数据类型更改为 decimal
而不是 double
,则以下内容有效。
decimal price = 100;
decimal smallestDiff = dictionary.Keys.Min(n => Math.Abs(n - price));
var nearest = dictionary.Where(n => Math.Abs(n.Key - price) == smallestDiff)
.OrderBy(n => n.Value).First();
如果您使用 double
,这可能会由于四舍五入问题而失败,但是 decimal
是与金钱有关的任何事情的首选,以避免这些问题。
你说你需要找到最接近的价格和最低的值,但你没有定义两者之间的优先级分配规则。在下面,我赋予它们相同的优先级:1 的价格距离相当于 1 的值。
var closest =
dictionary.OrderBy(kvp => Math.Abs(kvp.Key - price) + kvp.Value).First();
为了性能,OrderBy(…).First()
应替换为 MinBy(…)
运算符(如果可用)。
编辑:如果该值仅用作决胜局,则使用此(也由
var closest =
dictionary.OrderBy(kvp => Math.Abs(kvp.Key - price))
.ThenBy(kvp => kvp.Value)
.First();