我的情况是需求在一段时间后发生了变化。有问题的代码是读取一个巨大的CSV文件,其中的行通过标识符和一对系统/用户名代表用户。
hgulzar;ActiveDirectory1;hgulzar@dev.domain.de;ActiveDirectory2;hgulzar@dev-ref.de
someusr;ActiveDirectory1;someusr@dev.domain.de;ActiveDirectory1;someusr@dev-ref.de
usrthre;ActiveDirectory1;usrthr1@dev.domain.de;ActiveDirectory1;usrthr2@dev-ref.de;ActiveDirectory1;usrthr3@dev.domain.de
最初,规则是每个系统都是唯一的,但现在要求已经改变,上面的示例行#2和#3也是有效的。现在唯一的例外是同一系统的用户名不能相同(纯副本)
下面,我逐行阅读文件,dataRow
是加载了分割字符串的数组。
// Data line
var dataRow = localReadLine.Split(new[] { ToolSettings.RightsSeperator }, StringSplitOptions.None);
// Trim each element
Array.ForEach(dataRow, x => dataRow[Array.IndexOf(dataRow, x)] = x.Trim());
然后,我加载一个匿名类型持有标识符并配对
// Extract System/Username pairs
var lookup = dataRow.Skip(1).Select((data, index) => new
{
lookup = index % 2,
index,
data
}).ToLookup(d => d.lookup);
以下是结构的调试会话截屏:
第一行:
第二行将在下一步失败
然后,根据原始要求,我将匿名类型转换为过滤字典,系统名称为关键字,现在失败了。
// Check for duplicates
var rights = lookup[0].Join(lookup[1], system => system.index + 1, username => username.index, (system, username) => new
{
system = system.data,
useraname = username.data
}).Where(d => !string.IsNullOrEmpty(d.system)).ToDictionary(d => d.system, d => d.useraname);
// rights => Key = System Identifier, Value = Username
第一行最终表格的屏幕截图:
由于显而易见的原因,第二行因“键已经在字典中”而失败。
我需要有这样的代码,以便它只能在这样的情况下失败:
dummyUser;ActiveDirectory1;dummy1@dev.domain.de;ActiveDirectory1;dummy1@dev.domain.de
重复意义,系统和名称。其他一切都是可以接受的。我需要迭代结果,这就是为什么我尝试添加一种计数器作为结果字典的值的键和元组。
帮助/指针赞赏。
再见!
更新
出于某种原因,这个问题因为代码分配而被拒绝投票。我想我在解释我的一个班轮问题时添加了太多细节。虽然这仍然是一个简单的问题。
无论如何,我在阅读了一些更好的输入之后终于找到了解决方案。以下是我解决问题的方法:
var rights = lookup[0].Join(lookup[1], system => system.index + 1, username => username.index, (system, username) => new
{
system = system.data,
useraname = username.data
}).Where(d => !string.IsNullOrEmpty(d.system)).Select(d => new Tuple<string, string>(d.system, d.useraname)).ToList();
答案 0 :(得分:0)
也许如果您分两步拆分解决方案:提取和验证
var separator = new []{ ';' };
var lines = File.ReadAllLines(@"C:\sample.txt")
.Select(line =>
{
var values = line.Split(separator, StringSplitOptions.None);
return new
{
User = values[0],
Items = values.Skip(1)
.Select ((value, index) => new { Number = index / 2, Value = value })
.GroupBy( group => group.Number)
.Select ( group => new
{
System = group.First().Value,
UserName = group.Last ().Value
})
.ToArray()
};
})
.ToArray();
// This will fail for duplicated system/username
if (lines.Any(line => line.Items.GroupBy(i => i.System + i.UserName)
.Any (g => g.Count() > 1)))
throw new ArgumentOutOfRangeException("Duplicated data");