C# 从输入列表创建树,然后在有子节点时增加一个计数器并检索父节点的id?

C# 从输入列表创建树,然后在有子节点时增加一个计数器并检索父节点的id?,c#,string,dictionary,binary-tree,binary-search-tree,C#,String,Dictionary,Binary Tree,Binary Search Tree,我有这样一个输入文本文件: Bunny -vs- Dog Bunny Corners -vs- Dog Corners Bunny Penalty -vs- Dog Penalty Duck -vs- Cat Tiger -vs- Lion Tiger Corners -vs Lion Corners 我需要生成一个输出文本文件,为这些匹配指定(原始id匹配id),以便预期输出为: 1: Bunny -vs- Dog 1-1: Bunny Corners -vs- Dog Corners 1-

我有这样一个输入文本文件:

Bunny -vs- Dog
Bunny Corners -vs- Dog Corners
Bunny Penalty -vs- Dog Penalty
Duck -vs- Cat
Tiger -vs- Lion
Tiger Corners -vs Lion Corners
我需要生成一个输出文本文件,为这些匹配指定(原始id匹配id),以便预期输出为:

1: Bunny -vs- Dog
1-1: Bunny Corners -vs- Dog Corners
1-2: Bunny Penalty -vs- Dog Penalty
2: Duck -vs- Cat
3: Tiger -vs- Lion
3-1: Tiger Corners -vs Lion Corners
因为兔子和狗玩了三次,所以他们在这种格式下得到了1-1或1-2(“原始比赛id-他们到现在为止见过的次数”)。我原本想拥有一本词典,但在词典中找到重复的内容似乎是件奇怪的事情

我应该如何实现一个树,其中每个父根是具有相应id的原始匹配,然后添加与子字符串角点或惩罚匹配的子项,它们将具有与父项相同的匹配id,但子项的任何更多出现都将增加计数器

Ex: 
"Bunny -vs- Dog" => parent node
"Bunny Corners -vs- Dog Corners => child of "Bunny -vs- Dog"
"Bunny Penalty -vs- Dog Penalty => another child of "Bunny -vs- Dog"
这个版本的答案解释了评论中提出的两个问题

请记住,如果更改文本格式,可能需要调整
Regex
以获得
secondWord

主代码:

//Path of the file you want to reading
const string readPath = @"C:\Users\ak\Desktop\testInput.txt";
//Path of the file you want to save to
const string writePath = @"C:\Users\ak\Desktop\testOutput.txt";

//Get the content of readPath
string[] lines = File.ReadAllLines(readPath);

//Create new List for firstWords
List<string> firstWords = new List<string>();
//Create new List for secondWords
List<string> secondWords = new List<string>();
//Create New List for Parents
List<Parent> parents = new List<Parent>();


//Go through each line of your file
int firstDigit = 1;
foreach (string line in lines)
{
    //Get the first word of the line
    string firstWord = line.Split(' ')[0];
    //Get the second word of the line
    Regex regex = new Regex(@"-vs-\s(\S+)"); 
    string secondWord = regex.Match(line).Groups[1].Value;

    //Add new Parent for the words if it doesn't exist already
    if (!parents.Where(o => o._firstWord == firstWord).Select(o => o._secondWord).Contains(secondWord))
    {
        parents.Add(new Parent(firstWord, secondWord, firstDigit));
        firstDigit++;
    }

    //Add firstWord to List
    firstWords.Add(firstWord);
    //Add secondWord to List
    secondWords.Add(secondWord);
}

//Go through each firstWord
int index = 0;
foreach (string word in firstWords)
{
    //Get the Parent corresponding to the word
    Parent parent = parents.Where(o => o._firstWord == word && o._secondWord == secondWords[index]).FirstOrDefault();

    //Add the numbers to the text lines
    if (parent._firstAppearance)
    {
        //Only one digit => ex: 1
        lines[index] = parent._firstDigit + ": " + lines[index];
        parent._firstAppearance = false;
    }
    else
    {
        //Two digits => ex: 1-2
        lines[index] = parent._firstDigit + "-" + parent._secondDigit + ": " + lines[index];
        parent._secondDigit++;
    }

    index++;
}

//Save text to new file
using (StreamWriter writer = new StreamWriter(writePath, true))
{
    foreach (string line in lines)
    {
        writer.WriteLine(line);
    }
}
class Parent
{
    public string _firstWord { get; }
    public string _secondWord { get; }
    public int _firstDigit { get; }
    public int _secondDigit { get; set; }
    public bool _firstAppearance { get; set; }

    public Parent(string firstWord, string secondWord, int firstDigit)
    {
        _firstWord = firstWord;
        _secondWord = secondWord;
        _firstDigit = firstDigit;
        _secondDigit = 1;
        _firstAppearance = true;
    }
}
不要忘记添加这些名称空间

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
这个版本的答案解释了评论中提出的两个问题

请记住,如果更改文本格式,可能需要调整
Regex
以获得
secondWord

主代码:

//Path of the file you want to reading
const string readPath = @"C:\Users\ak\Desktop\testInput.txt";
//Path of the file you want to save to
const string writePath = @"C:\Users\ak\Desktop\testOutput.txt";

//Get the content of readPath
string[] lines = File.ReadAllLines(readPath);

//Create new List for firstWords
List<string> firstWords = new List<string>();
//Create new List for secondWords
List<string> secondWords = new List<string>();
//Create New List for Parents
List<Parent> parents = new List<Parent>();


//Go through each line of your file
int firstDigit = 1;
foreach (string line in lines)
{
    //Get the first word of the line
    string firstWord = line.Split(' ')[0];
    //Get the second word of the line
    Regex regex = new Regex(@"-vs-\s(\S+)"); 
    string secondWord = regex.Match(line).Groups[1].Value;

    //Add new Parent for the words if it doesn't exist already
    if (!parents.Where(o => o._firstWord == firstWord).Select(o => o._secondWord).Contains(secondWord))
    {
        parents.Add(new Parent(firstWord, secondWord, firstDigit));
        firstDigit++;
    }

    //Add firstWord to List
    firstWords.Add(firstWord);
    //Add secondWord to List
    secondWords.Add(secondWord);
}

//Go through each firstWord
int index = 0;
foreach (string word in firstWords)
{
    //Get the Parent corresponding to the word
    Parent parent = parents.Where(o => o._firstWord == word && o._secondWord == secondWords[index]).FirstOrDefault();

    //Add the numbers to the text lines
    if (parent._firstAppearance)
    {
        //Only one digit => ex: 1
        lines[index] = parent._firstDigit + ": " + lines[index];
        parent._firstAppearance = false;
    }
    else
    {
        //Two digits => ex: 1-2
        lines[index] = parent._firstDigit + "-" + parent._secondDigit + ": " + lines[index];
        parent._secondDigit++;
    }

    index++;
}

//Save text to new file
using (StreamWriter writer = new StreamWriter(writePath, true))
{
    foreach (string line in lines)
    {
        writer.WriteLine(line);
    }
}
class Parent
{
    public string _firstWord { get; }
    public string _secondWord { get; }
    public int _firstDigit { get; }
    public int _secondDigit { get; set; }
    public bool _firstAppearance { get; set; }

    public Parent(string firstWord, string secondWord, int firstDigit)
    {
        _firstWord = firstWord;
        _secondWord = secondWord;
        _firstDigit = firstDigit;
        _secondDigit = 1;
        _firstAppearance = true;
    }
}
不要忘记添加这些名称空间

using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;

如果你改变顺序,你的答案就会失败。例如,将兔子惩罚与狗惩罚移到最后一行,现在不会:)谢谢@Ottxr,如果有一天我加上兔子惩罚,你的代码会起作用吗?既然我知道你只考虑了第一个单词?@CatyCatCat现在会:)如果你改变顺序,你的答案就会失败。例如,将兔子惩罚与狗惩罚移到最后一行,现在不会:)谢谢@Ottxr,如果有一天我加上兔子惩罚,你的代码会起作用吗?既然我认识你,就考虑第一个词吧?@CatyCatCat现在它会:)