在列表中查找缺少的必需值

时间:2019-06-16 14:21:21

标签: c# list linq

假设我们得到两个列表(可以是任何原始类型):

var arguments = new List<String>() {"a", "b", "c", "d", "e", "f", "g", "h"};
var required = new List<String>() {"c", "g"};

必需列表的所有值都必须在参数列表中。如果没有缺失,则返回null,否则返回缺失参数的列表。哦,要求的值不能多次出现,如果是这种情况,应该抛出异常。

这是我设法放在一起的东西:

private static IList<string> FindMissingRequiredValues(List<string> required, List<string> arguments)
        {
            var missing = new List<string>();
            foreach (var r in required)
            {
                if (!arguments.Contains(r))
                    missing.Add(r);
            }

            if (missing.Count == 0)
                missing = null;
            return missing;
        }

它可以工作,但不会处理重复项,而且看起来很丑。是否有一个通用的优雅解决方案(适用于任何原始类型)并且可以处理重复项(也许使用linq)?

再次澄清,应满足以下条件:

1)如果一个(或多个)必需值在参数列表中多次出现,则引发错误。这仅说明了必需的值,其他值可以在参数列表中多次出现。

2)它适用于任何原始数据类型

3)如果所有必需值在参数列表中恰好出现一次,则返回null。

4)如果参数列表中缺少某些必需的值,则返回缺失值的列表。

3 个答案:

答案 0 :(得分:2)

您要在此处根据列表检查两个条件。

  1. 如果列表中存在所有必需的列表元素,则返回null

  2. 如果缺少任何字段,请检查缺少的列表是否包含重复项。

    • 如果有重复则抛出异常
    • 否则返回列表

您在这里顺理成章

    // Except will give you list of elements from required list which are not present in arguments.
    var missing = required.Except(arguments); 

    // to return null we will check that missing list contains any value or not
    // if it is empty then retun null, which will satisfy your first condition
    if(!missing.Any()) 
        return null;
    else if(isDuplicate(arguments, required)) //Check for duplicates
         throw new Exception("Duplicate records");
    else
        return missing.Distinct().ToList(); //Else return distinct element from missing list.

根据您的评论,如果您想检查参数中的重复项,那么我添加了一个额外的函数,该函数将返回布尔值

public static bool isDuplicate(List<string> arguments, List<string> required)
{
    var group = arguments.GroupBy( i => i );
    foreach( var grp in group )
    {
        if(required.Contains(grp.Key) && grp.Count() > 1)
            return true;
    }
    return false;
}

POC:.Net Fiddle

答案 1 :(得分:1)

尝试一下

if(required.GroupBy(i => i).Any(g => g.Count > 1))
  throw new Exception("Duplicates found");
var missing = required.Except(arguments).ToList();
return missing.Lenght == 0 ? null : missing;

答案 2 :(得分:1)

如果您需要一个通用的解决方案,我会选择这样的东西:

static List<T> FindMissingRequiredElements<T>(List<T> required, List<T> arguments)
{
    // convert to Dictionary where we store the required item as a key against count for an item
    var requiredDict = required.ToDictionary(k => k, v => 0);

    foreach(var item in arguments)
    {
        if (requiredDict.ContainsKey(item)) // now we check each item in arguments
        {
            requiredDict[item]++; // if we have required, adding to count
            if (requiredDict[item] > 1) // if we met required item more than once, throw exception
            {
                throw new Exception($"Required item {item} appeared more than once!");
            }
        }
    }

    var result = new List<T>();
    // now we are checking for missing items
    foreach (var key in requiredDict.Keys)
    {
        if (requiredDict[key] == 0)
        {
            result.Add(key);
        }
    }

    return result.Any() // if there are missing items, return the list, if not - return null
        ? result
        : null;
}

这里的关键思想是使用“字典”来计算列表中我们出现了多少项必需项。