我不知道如何编写表达式/查询来从包含IList<ITaskData> taskDataList //1st Level
的2级深度列表中获取结果
例如:
IList
此处ITaskData
包含ITaskData
和IList<KeyValuePair<object, object>> TaskParams { get; set; } //2nd Level
包含
TaskData
因此假设TaskParams具有低于键值对
关键:位置
价值观:Stockroom,Salesfloor
关键:迭代
值:1,2
因此,我需要获取包含TaskParams
值库房和{1}的taskDataListType1
列表。
我可以通过foreach循环轻松完成,但我想使用Linq / Lambda,它是一个衬垫,更容易维护。
非常感谢您的支持。如果您需要更多说明,请告诉我。
foreach循环的工作代码:我在 IList<ITaskData> taskDataListType1 = new List<ITaskData>();
IList<KeyValuePair<object, object>> taskParams = null;
bool iteration = false;
bool location = false;
foreach (ITaskData taskData in taskDataList)
{
taskParams = taskData.TaskParams;
if (taskParams != null)
{
foreach (KeyValuePair<object, object> keyValuePair in taskParams)
{
if (keyValuePair.Key.ToString().Equals("ITERATION", StringComparison.OrdinalIgnoreCase))
{
if (int.Parse(keyValuePair.Value.ToString()) == 1)
{
iteration = true;
}
}
else if (keyValuePair.Key.ToString().Equals("LOCATION", StringComparison.OrdinalIgnoreCase))
{
if (keyValuePair.Value.ToString() == "StockRoom")
{
location = true;
}
}
if (iteration == true && location == true)
{
taskDataListType1.Add(taskData);
}
}
}
}
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
);
}
奇怪但是如果我把它放在逻辑之下它不起作用我的意思是我没有在tasks1中获得任何值
requestAlwaysAuthorization
以上截图的输出截图如下:
答案 0 :(得分:1)
如果您坚持在object
中使用KeyValuePair
,那么您的示例将如下所示:
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)
);
正如您所看到的,您需要将object
强制转换为精确类型,因此这种方法非常容易出错,如果您键入,很容易导致运行时异常,值集合将包含类型的项目与你的期望不同。
如果您需要按位置或迭代进行过滤,请在TaskParams类中将它们定义为属性,然后您的查询将变得更清晰,强类型且更不容易出错。请参阅以下示例:
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)
);
答案 1 :(得分:0)
试试这个:
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);
答案 2 :(得分:-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)));
上面的代码只是为了解释逻辑。您需要将对象转换为正确的类型(如果您了解它们)或使用其他比较方法。
答案 3 :(得分:-1)
假设您有以下代码返回符合逻辑条件的List<KeyValuePair<object, object>>
:
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();
但是,以我的私人观点,在您的情况下,foreach
的解决方案看起来更优雅和可读。
当然,此代码将抛出NullReferenceException
,因为keyValuePairs
未初始化。我没有初始化它,因为它是一个示例,并且您有自己的ITaskData
类并且具有正确的初始化。