简体   繁体   中英

Convert a text file to supply dictionary C#

What is the best solution to my problem? Let's say I want to open a text file like this;

[1 (100, 100, name)]
[2 (200, 200, name)]
[3 (300, 300, name)]

Using this text file I want to supply it to a Dictionary<int, Tuple<double, double, string>>

What I tried:

Dictionary<int, Tuple<double, double, string>> text_to_dictionary = new Dictionary<int, Tuple<double, double, string>>();
    
    foreach(var item TextFileToSupplyDictionary())
    {
     text_to_dictionary.add(item)
    }
    
    public Dictionary<int, Tuple<double, double, string>>  TextFileToSupplyDictionary()
            {
                var res = File
                    .ReadLines("textFile")
                    .Select(line => line.Split(','))
                    .GroupBy(item => Convert.ToInt32(item[0]))
                    .ToDictionary(groupValues => groupValues.Key, groupValues => groupValues.ToDictionary(item => Convert.ToDouble(item[1]), item => Convert.ToDouble(item[2])));
    
                return res;
            }

I didn't really know where I was going with this...

Also I have this error: 在此处输入图片说明

One way would be to either remove or split on the other characters in the string that you don't need, and then select the first item as the key and a tuple created from the other items as the value:

var dictionary = File
    .ReadLines("textFile")
    .Select(line => line.Split(new[] {'[', '(', ',', ')', ']'},
        StringSplitOptions.RemoveEmptyEntries))
    .ToDictionary(x => int.Parse(x[0]),
        x => new Tuple<double, double, string>(
            double.Parse(x[1]), double.Parse(x[2]), x[3].Trim()));

Usually, I'd be the last one to suggest Regex, but here ...

Disclaimer: Please do excessive testing ( performance / load / memory ... ) if you decide to use Regex!

This is a first approach:

using System;
using System.Text.RegularExpressions;
                    
public class Program
{
    public static void Main()
    {
        string dummyfile = "[1 (100, 100, name)]\n[2 (200, 200, name)]\n[3 (300, 300, name)]\n";
        
        var regex = new Regex(@"^\[(?<index>\d*)\s+\((?<num1>\d+),\s+(?<num2>\d+),\s+(?<name>.+)\)\]$", RegexOptions.Multiline );
        
        MatchCollection matches = regex.Matches(dummyfile);
        
        Console.WriteLine("Matches: {0}", matches.Count);
        foreach( Match match in matches )
        {
            Console.WriteLine("Found {0}: {1} | {2} | {3}", match.Groups["index"], match.Groups["num1"], match.Groups["num2"], match.Groups["name"]);
        }
    }
}

Which ran on dotnetfiddle: https://dotnetfiddle.net/Jbob0S

An example that's more tailored to your specific situation:

using System;
using System.Linq;
using System.Text.RegularExpressions;
                    
public class Program
{
    public static void Main()
    {
        string dummyfile = "[1 (100, 100, name)]\n[2 (200, 200, name)]\n[3 (300, 300, name)]\n";
        var regex = new Regex(@"\[(?<index>\d*)\s+\((?<num1>\d+),\s+(?<num2>\d+),\s+(?<name>.+)\)\]" );
        
        var result = dummyfile.Split('\n', StringSplitOptions.RemoveEmptyEntries).Select( l => DoTheMatch( l, regex )).ToList();
    
        foreach( var item in result )
        {
            Console.WriteLine("Found {0}: {1} | {2} | {3}", item.Index, item.Num1, item.Num2, item.Name);
        }
    }
    
    public static Data DoTheMatch( string line, Regex regex )
    {
        Match match = regex.Match(line);
        if( match.Success )
        {
            return new Data(){Index = int.Parse(match.Groups["index"].Value), Num1 = int.Parse(match.Groups["num1"].Value), Num2 = int.Parse(match.Groups["num2"].Value), Name= match.Groups["name"].Value};
        }
        throw new Exception( string.Format("Invalid line '{0}'", line) );
    }
}

public class Data
{
    public int Index {get; set;}
    public int Num1 {get; set;}
    public int Num2 {get; set;}
    public string Name {get; set;}
}

See https://dotnetfiddle.net/z8BLEM

Based on my understanding, below solution will work for you with regex. String.Split will fail if "name" in text file contain "[",",","(" etc characters. Please let me know if I missed something.

static void Main(string[] args)
    {
        var regex = new Regex(@"^\[(?<DicIndex>\d*)\s+\((?<FirstNumber>\d+),\s+(?<SecondNumber>\d+),\s+(?<name>.+)\)\]$", RegexOptions.Multiline);

        var res = File
          .ReadLines(@"C:\TEST\Dictionary.txt")
          .Select(item => regex.Matches(item))
          .Select(a => new { key = a[0].Groups[1].Value, value = new Tuple<double, double, string>(Convert.ToDouble(a[0].Groups[2].Value), Convert.ToDouble(a[0].Groups[3].Value), Convert.ToString(a[0].Groups[4].Value)) })
          .ToDictionary(key => key.key, value => value.value);
        Console.ReadKey();
    }

I think you can use this code. you forgot to create a Typle in your code just use Dictionary so you got error

var dictionary = File
            .ReadLines("textFile")
            .Select(e => e.Split("[(,)]".ToCharArray() , StringSplitOptions.RemoveEmptyEntries))
            .ToDictionary(key => int.Parse(key[0]), values => new Tuple<double, double, string>(
                Convert.ToDouble(values[1]), Convert.ToDouble(values[2]), values[3]));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM