2014-12-29 1 views
3

я работаю со следующей строкой:Нарезка/цикл через строку, содержащую круглые скобки в C#

(SENT (VBP (HPP (HP Vem))(VB kan)(VBP (VB få)(PMP (PM ATP)))(MADP (MAD ?)))) 

Я хотел бы сделать следующий вывод:

SENT -> VBP -> HPP -> HP 
SENT -> VBP -> VB 
SENT -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PMP -> PM 
SENT -> VBP -> MADP -> MAD 

Чтобы АРХИВ это я первый подумал пропустить все круглые скобки, начиная с самого начала, а затем идти глубже и глубже, если таковые имеются. (Возможно рекурсивная функция?)

Но так как есть на самом деле не функция для расщепления скобок, я попытался расщепление с (, а затем, когда циклический, искать ), как это:

var row = "(SENT (VBP (HPP (HP Vem))(VB kan)(VBP (VB få)(PMP (PM ATP)))(MADP (MAD ?))))"; 

    string[] splitP = row.Split('('); 

    for (int i = 0; i < splitP.Length; i++) 
    { 
     string data = splitP[i]; 

     // string[] dataSplit = data.Split(')'); 

     Console.WriteLine(data); 
    } 

    Console.ReadLine(); 

Но как вы можете видеть, я застрял, и вышеупомянутое даже не представляет того, что я пытаюсь сделать, потому что я узнал, что логика, о которой я думал, ошибается, и это невозможно сделать так.

Как я могу архивировать это?

Обновление.

экстренная больше тестовая линия:

(SENT (VBP (PPP (PP På)(NNP (NN grundval))(PPP (PP av))(NNP (DTP (DT en))(NN intervju)(PPP (PP efter)(NNP (NN experimentet)))(PPP (PP med)(PCP (DTP (DT de))(PC oinvigda)(VBP (HPP (HP som))(VB gjort)(NNP (JJP (JJ felaktiga))(NN bedömningar)))))))(VB kunde)(PNP (PN man))(VBP (VB dela)(PLP (PL in))(PNP (PN dem))(PPP (PP i)(NNP (RGP (RG tre))(NN grupper)(MIDP (MID :))(KNP (NNP (NN (a)))(PNP (PN de)(VBP (HPP (HP som))(ABP (AB faktiskt))(VB trodde)(SNP (SN att)(VBP (PNP (PN de))(VB bedömt)(ABP (AB riktigt))))))(MIDP (MID ,))(PNP (NNP (NN (b)))(PN de)(VBP (HPP (HP som))(VB trodde)(SNP (SN att)(VBP (DTP (DT de)(JJP (JJ själva)))(VB måste)(VBP (VB ha)(VBP (VB misstagit)(PNP (PN sig))(SNP (SN eftersom)(VBP (ABP (AB inte))(PNP (ABP (AB så))(PN många))(VB kan)(VBP (VB ha)(ABP (AB fel))(PPP (PP mot)(NNP (DTP (DT en))(JJP (JJ enda))(NN person))))))))))))(KN och)(PNP (NNP (NN (c)))(PN de)(KNP (VBP (HPP (HP som))(ABP (AB faktiskt))(VB var)(JJP (JJ medvetna))(PPP (PP om)(SNP (SN att)(VBP (PNP (PN de))(VB angav)(NNP (JJP (JJ felaktiga))(NN bedömningar))))))(KN men)(VBP (HPP (HP som))(ABP (AB inte))(VB ville)(VBP (VB avvika)(PPP (PP från)(NNP (NN gruppen)))))))))))(MADP (MAD .)))) 
+0

Карен кассу обновления для нового ввода :) – Lrrr

ответ

3

Вот еще один ответ, я стараюсь, чтобы сделать его легко понять:

public class Class1 
{ 
    public static void Main() 
    { 
     new Class1().myRec("(SENT (VBP (HPP (HP Vem))(VB kan)(VBP (VB få)(PMP (PM ATP)))(MADP (MAD ?))))", null); 
    } 


    public void myRec(string input, string start) 
    { 
     if (input == null) 
      return; 
     if (input[0] != '(' || input[input.Length - 1] != ')') 
     { 
      Console.WriteLine(start); 
      return; 
     } 
     int count = 0; 
     List<string> subStrs = new List<string>(); 

     input = input.Remove(0, 1); 
     input = input.Remove(input.Length - 1, 1); 
     int i = input.IndexOf(' '); 

     string nextInput = i>0?input.Substring(0, i):input; 

     if (start != null) 
      start = start + " -> " + nextInput; 
     else 
      start = nextInput; 

     input = input.Remove(0, i + 1); 

     string tempStr = ""; 
     for (int j = 0; j < input.Length; j++) 
     { 
      tempStr += input[j]; 
      if (input[j] == '(') 
       count++; 
      else if (input[j] == ')') 
      { 
       count--; 
       if (count == 0) 
       { 
        subStrs.Add(tempStr); 
        tempStr = ""; 
       } 
      } 
     } 
     if (subStrs.Count == 0) 
      subStrs.Add(tempStr); 

     subStrs.ForEach(delegate(string it) 
     { 
      new Class1().myRec(it, start); 
     }); 

    } 
} 

Он использует рекурсию, и он работает только тогда, когда ваш вход правильно, я имею в виду вас есть равное ( и ). Также я не программист на C#, поэтому я знаю, что этот код может быть значительно улучшен.

Редактировать заменить массив на список, чтобы сделать код более точным.

Edit 2, чтобы заставить его работать на вход, где не может содержать некоторые пробелы, как новый дополнительный больший тест случае ОП я внести некоторые изменения:

заменить это в моем коде:

 if (start != null) 
      start = start + " -> " + input.Substring(0, i); 
     else 
      start = input.Substring(0, i); 

с этим:

string nextInput = i>0?input.Substring(0, i):input; 

    if (start != null) 
     start = start + " -> " + nextInput; 
    else 
     start = nextInput; 

(я это уже)

и вот результат:

SENT -> VBP -> PPP -> PP 
SENT -> VBP -> PPP -> NNP -> NN 
SENT -> VBP -> PPP -> PPP -> PP 
SENT -> VBP -> PPP -> NNP -> DTP -> DT 
SENT -> VBP -> PPP -> NNP -> NN 
SENT -> VBP -> PPP -> NNP -> PPP -> PP 
SENT -> VBP -> PPP -> NNP -> PPP -> NNP -> NN 
SENT -> VBP -> PPP -> NNP -> PPP -> PP 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> DTP -> DT 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> PC 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> VBP -> HPP -> HP 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> VBP -> VB 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> VBP -> NNP -> JJP -> JJ 
SENT -> VBP -> PPP -> NNP -> PPP -> PCP -> VBP -> NNP -> NN 
SENT -> VBP -> VB 
SENT -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PLP -> PL 
SENT -> VBP -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> PP 
SENT -> VBP -> VBP -> PPP -> NNP -> RGP -> RG 
SENT -> VBP -> VBP -> PPP -> NNP -> NN 
SENT -> VBP -> VBP -> PPP -> NNP -> MIDP -> MID 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> NNP -> NN -> a 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> HPP -> HP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> SN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> MIDP -> MID 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> NNP -> NN -> b 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> HPP -> HP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> SN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> DTP -> DT 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> DTP -> JJP -> JJ 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> SN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> PNP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> PPP -> PP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> PPP -> NNP -> DTP -> DT 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> PPP -> NNP -> JJP -> JJ 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> VBP -> SNP -> VBP -> VBP -> VBP -> SNP -> VBP -> VBP -> PPP -> NNP -> NN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> KN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> NNP -> NN -> c 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> HPP -> HP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> JJP -> JJ 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> PP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> SNP -> SN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> SNP -> VBP -> PNP -> PN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> SNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> SNP -> VBP -> NNP -> JJP -> JJ 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> PPP -> SNP -> VBP -> NNP -> NN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> KN 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> HPP -> HP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> ABP -> AB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> VBP -> VB 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> VBP -> PPP -> PP 
SENT -> VBP -> VBP -> PPP -> NNP -> KNP -> PNP -> KNP -> VBP -> VBP -> PPP -> NNP -> NN 
SENT -> VBP -> MADP -> MAD 
+0

Hi @Ali. Это работает! Почти - если вы попытаетесь запустить мою большую тестовую строку (в обновленном вопросе), она сработает. На этой строке: http://i.gyazo.com/121c5b6bd1f5b3905417f4dc3e9d01bc.png – Karem

+0

@Karem Я знаю, что это потому, что я, хотя есть слово, всегда есть пробелы, но кажется, что нет, поэтому я обновил свой ответ, пожалуйста, проверьте и дайте мне знать, если что-то не так :) В вашем вводе есть (a) (b) и (c), которые приводят к сбою моей программы, и я исправляю эту проблему :) – Lrrr

+0

Спасибо за внимание! Похоже, вы его работали. Не могли бы вы заменить исходный код, чтобы он был в правильном состоянии? Когда я пытаюсь заменить то, что вы мне наставляете, - это не работает – Karem

0

Я бы разметить данные, итерацией маркеров для построения AST, которые представляют модель в соответствии с правилами любого у вас есть, а затем рекурсивный АСТ.

Редактировать: что-то здесь не совсем верно, но у меня нет времени его отлаживать.

using System; 
using System.Collections.Generic; 
static class Program 
{ 
    static void Main() 
    { 
     string input = "(SENT (VBP (HPP (HP Vem))(VB kan)(VBP (VB få)(PMP (PM ATP)))(MADP (MAD ?))))"; 
     Node root = new Node(), current = root; 
     var ast = new Stack<Node>(); 
     foreach (var token in Tokenize(input)) 
     { 
      switch(token) 
      { 
       case "(": 
        // new sub-node 
        Node next = new Node(); 
        current.Children.Add(next); 
        ast.Push(current); 
        current = next;      
        break; 
       case ")": 
        // go back a level 
        current = ast.Pop(); 
        break; 
       case " ": 
        // nothing 
        break; 
       default: 
        if (current.Value == null) 
         current.Value = token; 
        else 
         current.Args.Add(token); 
        break; 

      } 
     } 
     if (ast.Count != 0) throw new InvalidOperationException("unbalanced"); 

     Queue<Node> ancestors = new Queue<Node>(); 
     Write(ancestors, root); 
    } 

    private static void Write(Queue<Node> ancestors, Node node) 
    { 
     if(node.Children.Count == 0) 
     { 
      foreach(var parent in ancestors) 
      { 
       if (!string.IsNullOrWhiteSpace(parent.Value)) 
       { 
        Console.Write(parent.Value); 
        Console.Write(" -> "); 
       } 
      } 
      Console.WriteLine(node.Value); 
     } 
     else 
     { 
      ancestors.Enqueue(node); 
      foreach (var child in node.Children) 
      { 
       Write(ancestors, child); 
      } 
      ancestors.Dequeue(); 
     } 
    } 
    class Node 
    { 
     public string Value { get; set; } 
     private readonly List<Node> children = new List<Node>(); 
     private readonly List<string> args = new List<string>(); 
     public List<Node> Children { get { return children; } } 
     public List<string> Args { get { return args; } } 
    } 
    static IEnumerable<string> Tokenize(string value) 
    { 
     if (string.IsNullOrWhiteSpace(value)) yield break; 

     int last = -1, next; 
     char[] splits = {'(', ')', ' '}; 
     while((next = value.IndexOfAny(splits, ++last)) >= 0) 
     { 
      if (last != next) yield return value.Substring(last, next - last); 
      yield return value[next].ToString(); 
      last = next; 
     } 
    } 
} 
+0

Спасибо за ваш ответ @marc Gravell - кажется, что это не выскакивает правильно, когда ребенок скобка закончился. – Karem

+0

@Karem да, я уже редактировал «это не совсем правильно», но у меня нет времени его отлаживать. –

+0

Понятно, спасибо за усилия. Черт, 15 минут спустя все еще не могу найти, где он идет не так. – Karem

Смежные вопросы