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# Lambda表达式或Linq从列表中提取keyvaluepair的筛选结果?_C#_Linq - Fatal编程技术网

C# Lambda表达式或Linq从列表中提取keyvaluepair的筛选结果?

C# Lambda表达式或Linq从列表中提取keyvaluepair的筛选结果?,c#,linq,C#,Linq,我不知道如何编写表达式/查询来从包含KeyValuePair的2级深度列表中获取结果 例如: IList<ITaskData> taskDataList //1st Level 因此,假设TaskParams具有以下键值对 关键词:位置 价值观:仓库、卖场 关键词:迭代 数值:1,2 因此,我需要获取包含TaskParams值Stockroom和1的TaskData列表 我可以通过foreach循环轻松完成,但我想使用Linq/Lambda,它是一个线性系统,更易于维护 非常感谢

我不知道如何编写表达式/查询来从包含KeyValuePair的2级深度列表中获取结果

例如:

IList<ITaskData> taskDataList //1st Level 
因此,假设TaskParams具有以下键值对

关键词:位置 价值观:仓库、卖场

关键词:迭代 数值:1,2

因此,我需要获取包含TaskParams值Stockroom和1的TaskData列表

我可以通过foreach循环轻松完成,但我想使用Linq/Lambda,它是一个线性系统,更易于维护

非常感谢你的支持。请让我知道,如果你需要更多的澄清

foreach循环的工作代码:我在taskDataListType1中获得了所需的输出

奇怪,但如果我把它放在逻辑下面,它就不起作用了,我的意思是我在任务1中没有得到任何价值

    IList<ITaskData> taskDataListType1 = new List<ITaskData>();

    foreach (TaskData td in taskDataList)
    {
                var tasks1 = taskParams.Where(kvp => kvp.Key != null
                                                && kvp.Value != null
                                                && kvp.Key.ToString().Equals("LOCATION", StringComparison.OrdinalIgnoreCase)
                                                 && kvp.Value.ToString() == "StockRoom"
                                                && kvp.Key.ToString().Equals("ITERATION", StringComparison.OrdinalIgnoreCase)
                                                && int.Parse(kvp.Value.ToString()) == 1
                                                );
    }
以上查询的输出如下图所示:
应该是这样的:

var tasks = taskDataList.Where(
    i => i.TaskParams.Any(x => x.Key == "Location" && x.Value.Contains("Stockroom")) &&
         i.TaskParams.Any(x => x.Key == "Iteration" && x.Values.Contains(2)));
IList<ITaskData> taskDataList = new List<ITaskData> 
{
    new ITaskData
    {
        TaskParams = new List<KeyValuePair<object,object>>
        {
            new KeyValuePair<object, object>("Location", "Stockroom"),
            new KeyValuePair<object, object>("Location", "Salesfloor"),
            new KeyValuePair<object, object>("Iteration", 1),
            new KeyValuePair<object, object>("Iteration", 2)
        }
    },
    new ITaskData
    {
        TaskParams = new List<KeyValuePair<object,object>>
        {
            new KeyValuePair<object, object>("Location", "Stockroom"),
            new KeyValuePair<object, object>("Location", "Salesfloor"),
            new KeyValuePair<object, object>("Iteration", 101),
            new KeyValuePair<object, object>("Iteration", 2)
        }
    }
};
var result = taskDataList.Where(td => 
    td.TaskParams.Any(tp => ((string)tp.Key == "Location") && ((string)tp.Value == "Stockroom")) &&
    td.TaskParams.Any(tp => (string)tp.Key == "Iteration" && (int)tp.Value == 1)
    );
上面的代码只是为了解释逻辑。如果您知道对象或使用其他比较方法,则需要将对象强制转换为正确的类型。

尝试以下操作:

var results =
    taskDataList
        .Where(td => td.TaskParams != null)
        .Where(td =>
            td.TaskParams.Any(kvp =>
                kvp.Key != null
                    && kvp.Key.ToString().Equals("LOCATION", StringComparison.OrdinalIgnoreCase)
                    && kvp.Value != null
                    && kvp.Value.Equals("Stockroom"))
            && td.TaskParams.Any(kvp =>
                kvp.Key != null
                    && kvp.Key.ToString().Equals("ITERATION", StringComparison.OrdinalIgnoreCase)
                    && kvp.Value != null
                    && kvp.Value.Equals(1)))
        .ToList();
我已根据以下数据测试了此代码:

IList<ITaskData> taskDataList = new List<ITaskData>();

var taskData = new TaskData();
taskData.TaskParams.Add(new KeyValuePair<object, object>("Location", "Stockroom"));
taskData.TaskParams.Add(new KeyValuePair<object, object>("Location", "Salesfloor"));
taskData.TaskParams.Add(new KeyValuePair<object, object>("Iteration", 1));
taskData.TaskParams.Add(new KeyValuePair<object, object>("Iteration", 2));
taskDataList.Add(taskData);

假设您有以下代码,返回与逻辑条件匹配的列表:

public class ITaskData
{
    public List<KeyValuePair<object, object>> keyValuePairs { get; set; }
}

class Program
{
    private static List<ITaskData> list = new List<ITaskData>();

    private static void Main()
    {
        List<KeyValuePair<object, object>> result = new List<KeyValuePair<object, object>>();

        foreach (var a in list)
            foreach (var b in a.keyValuePairs)
                if (b.Value.ToString().Contains("Stockroom")) result.Add(b); 
                // Here I make .ToString().Contains("Stockroom")
                // You can add any required logics here
    }
}
您可以在LINQ中实现:

List<KeyValuePair<object, object>> result = 
    (from a in list 
     from b in a.keyValuePairs 
     where b.Value.ToString().Contains("Stockroom") 
     select b)
    .ToList();
或在LINQ方法链中:

List<KeyValuePair<object, object>> result = 
    (list
        .SelectMany(a => a.keyValuePairs, (a, b) => new {a, b})
        .Where(t => t.b.Value.ToString().Contains("Stockroom"))
        .Select(t => t.b)
    ).ToList();
然而,在我个人看来,在你的例子中,用foreachs的解决方案看起来更优雅和可读。 当然,由于keyValuePairs未初始化,此代码将引发NullReferenceException。我不初始化它,因为这是一个示例,您有自己的ITaskData类,并进行了适当的初始化。

如果您坚持在KeyValuePair中使用object,那么您的示例将如下所示:

var tasks = taskDataList.Where(
    i => i.TaskParams.Any(x => x.Key == "Location" && x.Value.Contains("Stockroom")) &&
         i.TaskParams.Any(x => x.Key == "Iteration" && x.Values.Contains(2)));
IList<ITaskData> taskDataList = new List<ITaskData> 
{
    new ITaskData
    {
        TaskParams = new List<KeyValuePair<object,object>>
        {
            new KeyValuePair<object, object>("Location", "Stockroom"),
            new KeyValuePair<object, object>("Location", "Salesfloor"),
            new KeyValuePair<object, object>("Iteration", 1),
            new KeyValuePair<object, object>("Iteration", 2)
        }
    },
    new ITaskData
    {
        TaskParams = new List<KeyValuePair<object,object>>
        {
            new KeyValuePair<object, object>("Location", "Stockroom"),
            new KeyValuePair<object, object>("Location", "Salesfloor"),
            new KeyValuePair<object, object>("Iteration", 101),
            new KeyValuePair<object, object>("Iteration", 2)
        }
    }
};
var result = taskDataList.Where(td => 
    td.TaskParams.Any(tp => ((string)tp.Key == "Location") && ((string)tp.Value == "Stockroom")) &&
    td.TaskParams.Any(tp => (string)tp.Key == "Iteration" && (int)tp.Value == 1)
    );


你想要什么结果?这是一本字典,一些字符串还是什么?“获取”是什么意思?请包含您的foreach循环代码,以便其他人可以定义outputHi Yeldar,我需要任务数据收集的结果,即列表。Fetch表示过滤后的数据,如只有那些具有TaskParams位置值的TaskData具有Stockroom和迭代具有1Hi Dika,输出应包含具有TaskParams位置值的TaskData列表,如Stockroom和迭代具有1。我还没有开发foreach循环。“Stockroom,salesfool”代表一个对象还是多个对象?为什么1个键的值大于1?谢谢,这看起来很完美。在单击“更正”之前,让我运行代码。您尝试过此代码吗?当x.Key是一个对象并且您使用==时,您正在进行引用比较。因此,您可以有两个值相同但内存位置不同的字符串,这将失败。。。方法。是的,你需要把它转换成正确的类型。代码只是一个例子example@FabioLuz-您无法将其转换为正确的类型。不同的类型被添加到键值对中。您可能需要使您的答案更加可靠。OP需要指定TaskParams的taskDataList子集,而不是KeyValuePair本身。您也只是在查询两个必需的TaskParam中的一个。@Enigmativity我已经阅读了问题和注释3次,但还不明白OP到底想要什么。这都是关于问题的不明确。查询这两个参数中的一个怎么样?我展示的是如何生成LINQ,而不是如何过滤TaskParams。这就是为什么这里有一个注释添加任何逻辑。您的代码仅基于一个KVP进行选择。OP要求返回TaskData,其中两个KVP具有某些键和值。你必须重写你的代码来满足这个需求。嗨,Alexey,我仍然是空的,请看一下我添加到问题中的图片。我发现它在运行时是字符串类型,所以像这样更改查询,尽管有5个以上的TaskParams包含stockroom和1这样的值,但它仍然为null。var result=taskDataList.Wheretd=>td.TaskParams.Anytp=>stringtp.Key==LOCATION&&stringtp.Value==StockRoom&&td.TaskParams.Anytp=>stringtp.Key==ITERATION&&stringtp.Value==1@Subodh,请澄清你在哪里得到空值。从我在屏幕截图上看到的内容来看,这个TaskParams包含迭代=1和位置=Stockroom,因此我认为它没有问题。@Subodh-从您的图像中可以看出,元素5、6和7可能有空值。另外,由于在代码中只使用字符串,为什么不更改为KeyValuePair?我本来希望taskdata的收集结果是这样的,但它显示了predicate=null&source=null。Hi Enigmativity,实际上这是在框架级别完成的,我无法更改。我在应用层工作。是的,元素5,6,7是空的,我想是为了将来的用途。嗨,神秘性,我仍然得到空谓词,查询中的源,请看一下我添加到问题中的图像。我发现它在运行时是字符串类型,所以更改如下查询,
尽管有5个以上的TaskParam包含stockroom和1等值,但它仍然给我null。var query=taskDataList.Wheretd=>td.TaskParams.Anykvp=>kvp.Key.EqualsLOCATION&&kvp.Value.EqualsStockRoom&&td.TaskParams.Anykvp=>kvp.Key.EqualsITERATION&&kvp.Value.Equals1@Subodh-您需要发布ITaskData实现的定义。它有很多属性,如图所示。但是我只需要使用Taskparam,它是通过以下方式实现的:public-IList-TaskParams{get;set;}@Subodh-我要求实现,以便能够看到所有内容是如何实例化的。仅凭房产本身是不足以看到这一点的。如果你觉得代码太多,那么也许可以把它放在上面并发布一个链接。我已经用foreach解决方案更新了这个问题,它正在工作。我不能把整个实现看作是巨大的,我从Web服务中获得了价值。
public class TaskParamsType
{
    public IList<string> Locations;
    public IList<int> Iterations;
}

public class ITaskDataNew 
{
    public TaskParamsType TaskParams { get; set; } 
}

var result = taskDataList.Where(td => 
    td.TaskParams.Locations.Contains("Stockroom") &&
    td.TaskParams.Iterations.Contains(1)
    );