我有一个开发场景,我正在加入Linq的两个馆藏;包含表示元数据的列标题对象的单个列表,以及由Web服务调用产生的kv字典的枚举。我当前可以通过字典枚举迭代(for
),并将单个标题列表连接到当前的kv字典而不会出现问题。加入后,我会为每次迭代发出一个精选的字典值数组。
我想要做的是消除for
循环,并将单个标题列表直接连接到整个枚举。我理解1对1集合的连接非常好,但是1对N的语法让我望而却步。
详情
我有以下工作方法:
public void GetQueryResults(DataTable outputTable)
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
foreach (var row in odResponse)
{
var rowValues = OutputFields
.Join(row, h => h.Key, r => r.Key,
(h, r) => new { Header = h, ResultRow = r })
.Select(r => r.ResultRow.Value);
outputTable.Rows.Add(rowValues.ToArray());
}
}
odResponse
包含IEnumerable<IDictionary<string, object>>
; OutputFields
包含IList<QueryField>
; .Join
生成包含匹配字段元数据(.Header
)和响应kv对(.ResultRow
)的匿名枚举;最后,.Select
发出行消耗的匹配响应值。 OutputField
集合如下所示:
class QueryField
{
public string Key { get; set; }
public string Label { get; set; }
public int Order { get; set; }
}
宣称为:
public IList<QueryField> OutputFields { get; private set; }
通过将字段标题集合连接到响应行,我可以从响应中获取所需的列。如果标题键包含{“size”,“shape”,“color”}并且响应键包含{“size”,“mass”,“color”,“longitude”,“latitude”},我将得到一个数组{“size”,“shape”,“color”}的值,其中 shape 为null, mass ,经度,以及忽略纬度值。出于本场景的目的,我不关心订购。这一切都有效。
问题
我想要做的是重构此方法以返回值数组行的枚举,并让调用者管理数据的消耗:
public IEnumerable<string[]> GetQueryResults()
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
var responseRows = //join OutputFields to each row in odResponse by .Key
return responseRows;
}
跟进问题
Linq实现的此重构解决方案是否需要立即扫描枚举,还是可以传回惰性结果?重构的目的是改进封装而不用导致冗余的集合扫描。我总是可以构建命令式循环来重新格式化响应数据,但是我想从Linq那里得到的就是闭包。
感谢大家花时间阅读本文;任何建议表示赞赏!
答案 0 :(得分:0)
我不完全确定你的意思,但是你能说出这样的意思吗?
public IEnumerable<object[]> GetQueryResults()
{
var odClient = new ODataClient(UrlBase);
var odResponse = odClient.FindEntries(CommandText);
// i'd rather you linq here.
var responseRows = from row in odResponse
select new object[]
{
from field in row
join outputfield in OutputFields
on field.Key equals outputfield.Key
select field.Value
};
return responseRows;
}
而不是填充DataTable。这将创建一个对象数组,并使用field.Value填充它,其中field.Key存在于outputfields中。整个事情封装在IEnumerable
中。 (来自odResponse中的行)
用法:
var responseRows = GetQueryResults2();
foreach(var rowValues in responseRows)
outputTable.Rows.Add(rowValues);
这里的技巧是,在一个查询中,您迭代列表并在字段上创建子查询,并将子查询结果直接存储在object[]
中。 object[]
仅在迭代responseRows
时创建。这是我认为的第二个问题的答案 - &gt; 懒惰的结果。