私の問題に対する最善の解決策は何ですか?次のようなテキスト ファイルを開きたいとします。
[1 (100, 100, name)]
[2 (200, 200, name)]
[3 (300, 300, name)]
このテキスト ファイルを使用して、Dictionary<int, Tuple<double, double, string>> に提供したいと考えています。
私が試したこと:
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;
}
これをどこに行こうとしているのか本当にわかりませんでした...
また、次のエラーがあります。
テキスト ファイルの形式を制御できますか?それとも、「これが得られるものです、それに対処しましょう」でしょうか?
– フィルドール2020 年 9 月 3 日 11:48
foreach に in キーワードがありません
– エドゥアルド・コルトリ2020 年 9 月 3 日 11:49
辞書内の値は他の辞書ではなくタプルである必要があります。これがエラーが発生する理由です。
– モン・ジュウ2020 年 9 月 3 日 11:50
2
^^ dotnetfiddle.net/hIe4iv
– フィルドール2020 年 9 月 3 日 12:11
2
@Fildor いいですね、回答者として投稿してください :)
– モン・ジュウ2020 年 9 月 3 日 12:12
1 つの方法は、他のチャンネルを削除するか分割することです。文字列内の不要な文字を削除し、最初の項目をキーとして選択し、他の項目から作成されたタプルを値として選択します。
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()));
6
これで助かる! :)
– レッドビーフ2020 年 9 月 3 日 12:32
お役に立ててうれしいです。 int.Parse と double.Parse を盲目的に使用していることに注意してください。ファイルのこれらの部分を適切な型に解析できない場合は、例外をスローします。各行に検証を追加することでより安全にすることができますが、内容が適切に形成されている場合は、そのままで機能するはずです。
– ルーファス L2020 年 9 月 3 日 12:34
@Rufus、クエリが 1 つあります。「名前」を指定した場合、これは機能しますか?つまり、テキスト ファイルには ( 、 、 [ など?] のような文字が含まれています。
– ヴィカス・ガーグ2020 年 9 月 3 日 12:52
いいえ、それはこれも壊れてしまいます。それは有効なシナリオですか?
– ルーファス L2020 年 9 月 3 日 12:54
はい、壊れます。@redbeef、「名前」は壊れると思いますか?これらの文字を含むデータが存在することはありませんか?いいえの場合は、私が提供した正規表現ソリューションを使用することをお勧めします。何か見逃した場合はお知らせください。
– ヴィカス・ガーグ9月2020 年 3 月 13:00
通常、私は正規表現を最後に提案するところですが、ここでは...
免責事項: Regex を使用する場合は、過剰なテスト (パフォーマンス、負荷、メモリなど) を実行してください。
これは最初のアプローチです:
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"]);
}
}
}
dotnetfiddle で実行されたもの: https://dotnetfiddle.net/Jbob0S
特定の状況に合わせた例:
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;}
}
https://dotnetfiddle.net/z8BLEM を参照してください
私の理解に基づくと、以下の解決策は正規表現で機能します。 "name" の場合、String.Split は失敗します。テキスト ファイルには "[",",","(" などの文字が含まれています。何か見逃した場合はお知らせください。
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();
}
このコードを使用できると思います。コード内でタイプを作成するのを忘れたので、辞書を使用してください。そのため、エラーが発生しました。
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]));
1
1
[ ] 四角ブレーキを処理するのを忘れました。これは実行時に壊れます。変換できません
– モン・ジュウ2020 年 9 月 3 日 12:11