У меня есть следующая строка

 var string = "@anno1[ data1 xyz @anno2[data2  @anno3[data3] data4] data5 @anno4[data6] data7]"

И я хотел бы преобразовать его в объект следующим образом:

var childs = [ 
        {
            name : '@anno1',
            text : 'data1 xyz data2 data3 data4 data5 data6 data7',
        }, 
        {
            name : '@anno2',
            text : 'data2 data3 data4'
        }, 
        {
            name : '@anno3',
            text : 'data3'
        }, 
        {
            name : '@anno4',
            text : 'data6'
        } 
]

Я пробовал много способов, но безуспешно, заранее спасибо.

Вот код Java, который я пробовал

    import java.util.HashMap;
import java.util.Map;

public class ExpressionTree {

    static Map <String, String> resultMap = new HashMap<String, String>(16);

    public static void main(String args[]) {
        // String exp = "[data1 xyz @anno2[data2 @anno3[data3] data4] data5 @anno4[data6] data7]";

        String exp = "@anno1[ data1 xyz @anno2[data2  @anno3[data3] data4] data5 @anno4[data6] data7 ]";

        parseRecursively(exp);
    }

    private static void parseRecursively(String exp) {

        String annotation = null;
        String annotationValue = null;

        if (exp.startsWith("@")) {
            int dataStartIndex = exp.indexOf("[");
            annotation = exp.substring(0, dataStartIndex);
            annotationValue = exp.substring(0 + dataStartIndex, exp.lastIndexOf("]")+1).trim();

            System.out.println(annotation);
            System.out.println(annotationValue);

            resultMap.put(annotation, annotationValue);

            parseRecursively(annotationValue);

        } else {
            int annotationStartIndex = exp.indexOf("@");
            int dataStartIndex = exp.substring(1).indexOf("[");

            if( -1 != annotationStartIndex || -1 != dataStartIndex)
            {
                annotation = exp.substring(annotationStartIndex, dataStartIndex+1).trim();

                String nextData = exp.substring(0 + dataStartIndex + 1).trim();
                String tmpNextData = nextData;

                int countOfOpenBrackets = 0;
                for (int i = 0; tmpNextData.charAt(i) != ']'; i++) {
                    // System.out.println(tmpNextData.charAt(i));
                    if (tmpNextData.charAt(i) == '[') {
                        countOfOpenBrackets++;
                    }
                    // tmpNextData = tmpNextData.substring(1);
                }

                tmpNextData = nextData;
                int endIndexOfCurrentData = 0;

                for (int i = 0; i < tmpNextData.length() && endIndexOfCurrentData == 0; i++) {
                    // System.out.println(tmpNextData.charAt(i));
                    if (tmpNextData.charAt(i) == ']') {
                        countOfOpenBrackets--;
                    }
                    if (countOfOpenBrackets == 0) {
                        endIndexOfCurrentData = i + 1;
                    }
                    // tmpNextData = tmpNextData.substring(1);
                }

                annotationValue = nextData.substring(0, endIndexOfCurrentData).trim();

                System.out.println(annotation);
                System.out.println(annotationValue);

                resultMap.put(annotation, annotationValue);

                parseRecursively(annotationValue);
            }
        }
        System.out.println(resultMap);
    }
}
1
Sai Karnate 23 Июл 2017 в 20:37
Какие решения вы пробовали?
 – 
hbagdi
23 Июл 2017 в 20:42
Что заставило людей проголосовать против
 – 
Sai Karnate
23 Июл 2017 в 20:47
Привет, @hbagdi, я отредактировал ответ, теперь ты видишь
 – 
Sai Karnate
23 Июл 2017 в 20:50
1
Можете ли вы объяснить свой текущий подход вместо того, чтобы просто публиковать весь код? Гораздо легче понять, если есть также текст, объясняющий подход.
 – 
Zabuzard
23 Июл 2017 в 20:55
2
Вы ищете решение на javascript или java?
 – 
trincot
23 Июл 2017 в 20:56

1 ответ

Лучший ответ

Вот решение JavaScript (ES6):

function toObject(string) {
    "use strict";
    const tokens = string.match(/[\[\]]|[^\s\[\]]+/g),
        result = [];
    let i = 0;
    function recurse() {
        const words = [];
        let obj;
        while (i < tokens.length) {
            let token = tokens[i];
            if (token[0] === '@') {
                obj = {name: token};
                result.push(obj);
            } else if (token === '[') {
                i++;
                obj.text = recurse();
                words.push(obj.text);
            } else if (token === ']') {
                break;
            } else {
                words.push(token);
            }
            i++;
        }
        return words.join(' ');
    }
    recurse();
    return result;
}

const string = "@anno1[ data1 xyz @anno2[data2  @anno3[data3] data4] data5 @anno4[data6] data7]";
const result = toObject(string);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
1
trincot 23 Июл 2017 в 21:12
Ты гений, спасибо большое
 – 
Sai Karnate
23 Июл 2017 в 22:24
У меня есть новые строки и вкладки рядом с текстом, которые также должны быть включены в текст
 – 
Sai Karnate
16 Янв 2018 в 16:26
Если вы говорите, что только буквальный пробел ограничивает элементы, но не табуляцию или новую строку, тогда в регулярном выражении замените \s (который соответствует всем этим) просто пробелом.
 – 
trincot
16 Янв 2018 в 19:12