C# Lambda表达式或Linq从列表中提取keyvaluepair的筛选结果?
我不知道如何编写表达式/查询来从包含KeyValuePair的2级深度列表中获取结果 例如: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,它是一个线性系统,更易于维护 非常感谢
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)
);