【问题标题】:C# split string to array then to key value pair in dictionaryC# 将字符串拆分为数组,然后拆分为字典中的键值对
【发布时间】:2018-03-01 20:53:55
【问题描述】:

我目前正在将带有多个分隔符的字符串传递给我想最初将 (at ~) 拆分为字符串数组的方法,然后将数组中的每个条目 (at |) 传递给字典 ("key "="值")。

~timestamp=Mar  1 2018  3:14PM|proc=procedure A|tran=transaction 1|rowCount=987
~timestamp=Mar  1 2018  3:14PM|proc=procedure B|tran=transaction 2|rowCount=654
~timestamp=Mar  1 2018  3:14PM|proc=procedure C|tran=transaction 3|rowCount=321

我可以完成初始拆分为单独的“行”

~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987

与:

string result = <<long string>>;
string filepath = <<filepath variable>>;
string[] resultRows = result.Split('~');

try
{
    foreach (string row in resultRows)
    {
        if (!File.Exists(filepath))
        {
            using (StreamWriter log = File.CreateText(filepath))
            {
                log.WriteLine(row);
            }
        }
        else
        {
            using (StreamWriter log = File.AppendText(filepath))
            {
                log.WriteLine(row);
            }
        }
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

但是,当我尝试将这些“行”中的每一个解析为字典时,会引发错误(索引超出数组的范围)。

string result = <<long string>>;
string filepath = <<filepath variable>>;
string[] resultRows = result.Split('~');
Dictionary<string, string> dict = new Dictionary<string, string>();

try
{
    foreach (string row in resultRows)
    {
        var results = row.Split('|').Select(s => s.Split(new[] { '=' }));

        foreach (var item in results)
        {
            dict.Add(item[0], item[1]);
        }
    }
}
catch (Exception e)
{
    Console.WriteLine(e.Message);
}

我假设我对字典的期望不正确 - 对于字典中的每个“条目”,我希望看到以下内容:

~timestamp=>Mar 1 2018 3:14PM, proc=>procedureA, tran=>transaction1, rowCount=>987

这样我就可以将每一行写入一个日志文件,在那里我可以单独访问每个键的值。如果我对如何在字典中设置/获取值的理解还差得很远,有没有更好的方法来完成这项任务?

【问题讨论】:

  • 抛出时item.Length是什么?
  • 我相信我“修复”了显示输入行,使得每一行都是统一的,并且显示时没有换行,请验证确实如此。
  • 您的数据以“~”开头。你认为"~something".Split('~'); 的结果是什么?如果你再次用“|”分割每个分割字符串部分,结果是什么......?使用调试器,看看会发生什么。 (提示:StringSplitOptions.RemoveEmptyEntries)
  • 您必须删除第一个“~”。它返回一个空行
  • 键是唯一的,因此您不能拥有多个名为“proc”或“timestamp”的键。请详细描述在处理文件中的前五个“行”之后字典的实际外观(每个 KeyValuePair)。如果您只想将每一行写入日志文件,也许您需要一个List&lt;CustomClass&gt;,而您的CustomClass 将具有TimestampProcedureTransactionRowCount 的属性。跨度>

标签: c# arrays dictionary


【解决方案1】:

主要问题可能是空的拆分部分,在进一步拆分后尝试通过dict.Add(item[0], item[1]); 中的索引访问它们 - 如果只有一个结果,则它的索引越界异常。

在您的拆分~ 数组上使用 IEnumerable.Aggregate() 的固定版本:

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
    public static void Main(string[] args)
    {
        var dd = new Dictionary<string, Dictionary<string, string>>();
        var data = 
        "~timestamp=Mar 1 2018 3:14PM|proc=procedure A|tran=transaction 1|rowCount=987" +
        "~timestamp=Mar 1 2018 3:14PM|proc=procedure B|tran=transaction 2|rowCount=654" +
        "~timestamp=Mar 1 2018 3:14PM|proc=procedure C|tran=transaction 3|rowCount=321";


        // splitting is done here:

        var d = data  
            .Split(new[] { '~' }, StringSplitOptions.RemoveEmptyEntries) 
            .Aggregate(new List<Dictionary<string, string>>(), 
            (listOfDicts, part) =>
            {
                var key = Guid.NewGuid().GetHashCode().ToString();
                listOfDicts.Add(new Dictionary<string, string>());

                foreach (var p in part.Split(new[] { '|' },
                                             StringSplitOptions.RemoveEmptyEntries))
                {
                    // limit split to 2 parts if more then 1 = inside
                    var kvp = p.Split(new[] { '=' }, 2,
                                      StringSplitOptions.RemoveEmptyEntries);

                    // either 2 or 1 is the result, handle both:
                    if (kvp.Count() == 2)
                        listOfDicts.Last()[kvp[0]] = kvp[1];
                    else
                        listOfDicts.Last()[kvp[0]] = null;
                }
                return listOfDicts;
            });


        // output:

        foreach (var k in d)
        {
            Console.WriteLine();
            foreach (var innerKvp in k)
            {
                Console.WriteLine("    " + innerKvp.Key + "    " + innerKvp.Value);
            }
        }
        Console.ReadLine();
    }
}

输出:(字典列表)

timestamp    Mar 1 2018 3:14PM
proc    procedure A
tran    transaction 1
rowCount    987

timestamp    Mar 1 2018 3:14PM
proc    procedure B
tran    transaction 2
rowCount    654

timestamp    Mar 1 2018 3:14PM
proc    procedure C
tran    transaction 3
rowCount    321

【讨论】:

  • 这绝对为我指明了正确的方向——非常感谢!
【解决方案2】:

以下函数应该能够正确解析您的输入:

private static List<Dictionary<String,String>> ParseData(String data)  
{
    String[] entriesData = data.Split(new Char[] { '~' },StringSplitOptions.RemoveEmptyEntries);
    List<Dictionary<String,String>> result = new List<Dictionary<String,String>>(entriesData.Length);

    foreach (String entryData in entriesData)
    {
        String[] entryDataPairs = entryData.Split(new Char[] { '|' },StringSplitOptions.RemoveEmptyEntries);
        Dictionary<String,String> entryResult = new Dictionary<String,String>(entryDataPairs.Length);

        foreach (String entryDataPair in entryDataPairs)
        {
            String[] kvp = entryDataPair.Split(new Char[] { '=' },StringSplitOptions.RemoveEmptyEntries);
            entryResult.Add(kvp[0], kvp[1]);
        }

        result.Add(entryResult);
    }

    return result;
}

以下输入字符串产生的结果:

~timestamp=Mar  1 2018  3:14PM|proc=procedure A|tran=transaction 1|rowCount=987~timestamp=Mar  1 2018  3:14PM|proc=procedure B|tran=transaction 2|rowCount=654~timestamp=Mar  1 2018  3:14PM|proc=procedure C|tran=transaction 3|rowCount=321

是:

--- ENTRY ---
timestamp = Mar  1 2018  3:14PM
proc = procedure A
tran = transaction 1
rowCount = 987

--- ENTRY ---
timestamp = Mar  1 2018  3:14PM
proc = procedure B
tran = transaction 2
rowCount = 654

--- ENTRY ---
timestamp = Mar  1 2018  3:14PM
proc = procedure C
tran = transaction 3
rowCount = 321

访问this link试试看!

【讨论】:

    【解决方案3】:

    试试这样的:

    var dictionary = new Dictionary<string, string>();
    
    foreach (var resultRow in resultRows)
    {
        if(!string.IsNullorEmpty(resultRow))
        {
            var rowItems = resultRow.Split('|').ToList();
    
            dictionary.Add(rowItems.First(), string.Join("|", rowItems.Skip(1));
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-13
      • 1970-01-01
      相关资源
      最近更新 更多