是否有一种以懒散的方式使用LINQ到(内部)连接集合的方法?我所面临的情况是,我需要将级联中的多个CSV关联起来,如果“上游”CSV被证明是空的,我希望避免不必要的解析操作:
ReadCsvRows(fileA).Join(
ReadCsvRows(fileB), // why to parse B if A is empty?!
...
).Join(
ReadCsvRows(fileC),
...
).Join(...)
注意,ReadCsvRows
方法位于接口后面,唯一的要求是该方法必须返回IEnumerable
(如描述的这里)。为了保持"streamy",我可以通过引入自定义扩展方法来解决这个问题。
public static IEnumerable<TResult> Join<TOuter, TInner, TKey, TResult>(
this IEnumerable<TOuter> outer,
Func<IEnumerable<TInner>> innerFunc,
Func<TOuter, TKey> outerKeySelector,
Func<TInner, TKey> innerKeySelector,
Func<TOuter, TInner, TResult> resultSelector) =>
!outer.Any() ?
Array.Empty<TResult>() :
outer.Join(
innerFunc(),
outerKeySelector,
innerKeySelector,
resultSelector
);
但我想知道我有什么选择的香草LINQ。
发布于 2022-02-01 06:05:26
您不需要自己的Join
实现。如果标准System.Linq
实现没有记录,则不枚举inner
序列。
因此,检查您的ReadCsvRows
实现。如果在它的体内使用yield return
,就不会出现不必要的读取。
按示意图:
public static IEnumerable<Row> ReadCsvRows(string fileName)
{
using var reader = new CsvReader(fileName);
while (reader.ReadNext())
{
yield return reader.CurrentRow;
}
}
在这种情况下,如果第一个序列没有行,即使new CsvReader(fileName)
也不会被调用。
发布于 2022-02-01 04:45:05
如果我是您,我会将ReadCsvRows(fileB)和ReadCsvRows(fileC)分割成两个独立的变量。并添加一个" if“条件来确定是否应该执行"ReadCSVRows(fileB)”。
就像这样:
List<FileATypeA> fileAData = ReadCsvRows(fileA);
List<FileATypeB> fileBData = new List<FileATypeB>();
List<FileATypeC> fileCData = new List<FileTypeC>();
if(fileAData.Count() > 0)
fileBData = ReadCsvRows(fileB);
if(fileBData.Count() > 0)
fileCData = ReadCsvRows(fileC);
List<FinalType> final = from a in fileAData
join b in fileBData
on a.Key = b.Key
join c in fileCData
on b.Key = c.Key
看看这是否有帮助
https://stackoverflow.com/questions/70940626
复制