【问题标题】:Splitting paired values in a CSV在 CSV 中拆分配对值
【发布时间】:2015-05-28 12:25:28
【问题描述】:

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

【问题讨论】:

  • SO 不是代码编写服务。尽你最大的努力回来解决具体问题。
  • 我会使用 KeyValuePairs (List&lt;KeyValuePair&lt;string, string&gt;&gt;) 的列表来停止错误“键已在字典中”,并且您仍然可以迭代列表。然后,您需要检查列表中的确切重复项。
  • 这个问题尽可能直接和切中要害。 ToDictionary 由于所需的重复键而失败。需要有其他东西来代替仍然允许迭代。

标签: c# linq csv lookup


【解决方案1】:

也许如果您将解决方案分为两个步骤:提取和验证

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

【讨论】:

    猜你喜欢
    • 2010-11-06
    • 1970-01-01
    • 2021-07-14
    • 1970-01-01
    • 1970-01-01
    • 2013-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多