在CSV中拆分配对值

时间:2015-05-28 12:25:29

标签: c# linq csv lookup

我的情况是需求在一段时间后发生了变化。有问题的代码是读取一个巨大的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);

以下是结构的调试会话截屏:

第一行: Good row lookup

第二行将在下一步失败 Bad row 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

第一行最终表格的屏幕截图: Good row result

由于显而易见的原因,第二行因“键已经在字典中”而失败。

我需要有这样的代码,以便它只能在这样的情况下失败:

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();

1 个答案:

答案 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");