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 - Fatal编程技术网

C# 在查找最小值时避免使用幻数

C# 在查找最小值时避免使用幻数,c#,linq,C#,Linq,我需要按键在字典列表中找到min。我是这样做的: public int GetMin(string key, List<Dictionary<string,int>> db) { if (db==null || db.Count==0) { return 0; } int result = Int32.MaxValue;

我需要按键在字典列表中找到min。我是这样做的:

public int GetMin(string key, List<Dictionary<string,int>> db)
        {
            if (db==null || db.Count==0)
            {
                return 0;
            }

            int result = Int32.MaxValue;

            foreach (var dic in db)
            {
                if (dic.TryGetValue(key,out int value) && result>value)
                {
                    result = value;
                }
            }
            return result == Int32.MaxValue ? 0 : result;
        }
有没有办法做得更好更有效

我也试着用Linq做这个,但是看起来有点难看。也许用linq更容易做到这一点

  var result =  db.SelectMany(d => d)?.Where(kvp=>kvp.Key==key)?.OrderBy(x=>x.Value).FirstOrDefault().Value;
            return result ?? 0;

您可以编写一个函数,在其中可以检查字典中是否有

若字典包含键,则从中返回
Min
,若不存在,则返回0

实施:

   public static int GetMinFromDictionaryList(List<Dictionary<string, int>> parameter, string key)
    {
        var keyValuePairList = parameter.SelectMany(d => d).Select(x => x.Key);
        if (keyValuePairList.Contains(key))
        {
            return parameter.SelectMany(d => d).Where(x => x.Key == key).ToList().Min(x => x.Value);
        }
     return 0;
    }
public static int GetMinFromDictionaryList(列表参数,字符串键)
{
var-keyValuePairList=parameter.SelectMany(d=>d).Select(x=>x.Key);
if(keyValuePairList.Contains(key))
{
返回参数.SelectMany(d=>d).Where(x=>x.Key==Key).ToList().Min(x=>x.Value);
}
返回0;
}

POC:

一种避免使用
Int32.MaxValue
作为基线并避免在未找到结果时返回
0
的方法是使用
null
,或使用缩写
int?

public static int? GetMin(string key, List<Dictionary<string, int>> db)
{
    int? result = null;
    if (db != null) {
        foreach (var dic in db) {
            if (dic.TryGetValue(key, out int value) && (result == null || value < result)) {
                result = value;
            }
        }
    }
    return result;
}
在方法中使用可为null的int仍然很有用,因为它允许我们避免滥用
Int32.MaxValue
。现在,
Int32.MaxValue
可以是有效的输入和结果

循环没有问题。不是每件事都需要灵巧。如果要使用LINQ,请确保使用
Min
重载处理空值。不可为null的变量为空输入引发异常。列举字典的LINQ变体(使用
SelectMany
)没有利用快速字典查找的优势,效率低下

public static int? GetMinLINQ(string key, List<Dictionary<string, int>> db)
{
    if (db == null) {
        return null;
    }
    return db
        .Select(d => (isMatch: d.TryGetValue(key, out int i), result:i))
        .Where(x => x.isMatch)
        .Select(x => (int?)x.result)
        .Min();
}
公共静态int?GetMinLINQ(字符串键,列表数据库)
{
if(db==null){
返回null;
}
返回数据库
.选择(d=>(isMatch:d.TryGetValue(键,out int i),结果:i))
.其中(x=>x.isMatch)
.选择(x=>(int?)x.result)
.Min();
}

它将
TryGetValue
的返回值和
out
变量组合成一个值元组。但是得到的方法并不比使用循环的方法短。

我不知道问题出在哪里,这应该很简单

请看下面的例子

public static void Main()
{
   var db = new List<Dictionary<string, int>>()
        {
            new Dictionary<string, int>(){ {"a", 1 }, { "b", 5 }, { "c", 3 } },
            new Dictionary<string, int>(){ {"d", 5 }, { "b", 3 } },
            new Dictionary<string, int>(){ {"a", 2 }, { "c", 2 } },
        };
    // Result you will get is 1
    Console.Write(GetMin(db, "a").ToString());

}

public static int GetMin(List<Dictionary<string, int>> db, string key)
{
        return db == null || !db.Any(x=> x.ContainsKey(key)) ? 0 :
        db.SelectMany(x=> x).Where(x=> x.Key == key).Select(x=> x.Value).Min();

}
publicstaticvoidmain()
{
var db=新列表()
{
新字典(){“a”,1},{“b”,5},{“c”,3},
新字典(){“d”,5},{“b”,3},
新字典(){“a”,2},{“c”,2},
};
//您将得到的结果是1
Write(GetMin(db,“a”).ToString();
}
公共静态int GetMin(列表数据库,字符串键)
{
返回db==null | |!db.Any(x=>x.ContainsKey(key))?0:
其中(x=>x.Key==Key).Select(x=>x.Value).Min();
}

由于LINQ查询中唯一的问题是在集合为空时计算最小值(未找到匹配的键,因此引发异常),因此在
Min()
之前加上
筛选器未返回任何元素时,只需返回
0

不需要使用空值或预筛选:

public int GetMin(string key, List<Dictionary<string, int>> db)
{
    if (db is null) return 0;
    return  db.SelectMany(d => d).Where(kvp => kvp.Key == key).DefaultIfEmpty().Min(v => v.Value);
}
public int GetMin(字符串键,列表数据库)
{
如果(db为空)返回0;
返回db.SelectMany(d=>d).Where(kvp=>kvp.Key==Key).DefaultIfEmpty().Min(v=>v.Value);
}

您可以将其作为LINQ方法的一个序列来编写

因此,您有一个字符串
和一系列类似的字典,每个字典都是一个
字典
。您需要字典键等于“key”的最小整数值。如果所有项目都不包含
,则希望返回零

幸运的是,
Dictionary
实现了
IEnumerable
,因此您可以使用
SelectMany
Where
Select
Aggregate

string key = ...
List<Dictionary<string, int>> myListOfDictionaries = ...
// note: this implements IEnumerable<IEnumerable<KeyValuePair<string, int>>>
// so a sequence of sequences of KeyValuePairs

var smallestIntThatHasKey = myListOfDictionaries

    // make one list containing all keyValuePairs
    .SelectMany(dictionary => dictionary)
    // result: one sequence of KeyValuePairs

    // keep only those KeyValuePairs where the Key equals key
    .Where(keyValuePair => keyValuePair.Key == key)
如果没有带键的项,则会正确返回零。这也不是一个非常聪明的解决方案:如果您在排序顺序中找到了第一个元素(最小),那么如果您只打算使用第一个元素,为什么还要麻烦对第二个、第三个等元素进行排序呢。更好地使用聚合

.Select(keyValuePair => keyValuePair.Value)
.Aggregate(0,(minValue, enumeratedValue) =>
    (enumeratedValue < minValue) ? enumeratedValue : minValue);
.Select(keyValuePair=>keyValuePair.Value)
.聚合(0,(最小值,枚举值)=>
(enumeratedValue

这将为聚合结果添加零种子。它将只通过一个序列:它将用枚举值检查MimValk并将最小值作为聚合值

IDK,如果我考虑使用魔法值。它有一个清晰的名称,从上下文来看它的用途应该相当明显。预期的输出是什么。@Carcigenicate,如果字典包含Int32.MaxValue怎么办?@Prasadelkikikar,在我上面的例子中,如果我们传递“a”,那么结果是1,如果“b”,那么结果是3,如果“e”,那么结果是0,如果“c”,那么linq post是最简单的。如果有字典就容易多了。如果字典中没有具有给定键的值,则会引发异常。@user194076,现在它支持上述注释中提到的条件在函数中创建可空int
result
,并在返回结果时使用空合并运算符,我相信这是多余的。。如果我错了,请详细说明为什么使用
int?结果
。您可以直接使用
result=0
,并像我在回答中那样返回结果。这取决于您是否希望能够区分结果“未找到匹配”(=
null
)和“找到此最小值”。然后使用
int?
作为结果类型是合适的。如果您想返回
0
,那么
int?
在方法内部仍然很有用,可以避免使用
Int32.MinValue
。当然,你也可以使用一个单独的
bool
标志。这对我来说是正确的方法。许多人忽略了一个事实,即
Min
Max
的可空重载
public int GetMin(string key, List<Dictionary<string, int>> db)
{
    if (db is null) return 0;
    return  db.SelectMany(d => d).Where(kvp => kvp.Key == key).DefaultIfEmpty().Min(v => v.Value);
}
string key = ...
List<Dictionary<string, int>> myListOfDictionaries = ...
// note: this implements IEnumerable<IEnumerable<KeyValuePair<string, int>>>
// so a sequence of sequences of KeyValuePairs

var smallestIntThatHasKey = myListOfDictionaries

    // make one list containing all keyValuePairs
    .SelectMany(dictionary => dictionary)
    // result: one sequence of KeyValuePairs

    // keep only those KeyValuePairs where the Key equals key
    .Where(keyValuePair => keyValuePair.Key == key)
.Select(keyValuePair => keyValuePair.Value)
.OrderBy(value => value)
.FirstOrDefault();
.Select(keyValuePair => keyValuePair.Value)
.Aggregate(0,(minValue, enumeratedValue) =>
    (enumeratedValue < minValue) ? enumeratedValue : minValue);