【问题标题】:Convert String into nested ArrayList in Java在Java中将String转换为嵌套的ArrayList
【发布时间】:2016-05-15 07:00:55
【问题描述】:

我有一个字符串:

    String input = {{a,b,c}, 4,6, 7 , {c, d, {g,h, {} }}};

我需要将“输入”转换为嵌套的 ArrayList,其中每个“{}”中的内容位于单独的列表中。请注意,输入中有随机空格,在将每个元素添加到列表中之前需要对其进行修剪。 因此,所需的输出需要是(在 toString() 方法中描述的输出用于表示):

    List<Object> output = [[a,b,c],4,6,7,[c,d,[g,h,[]]]]

在这里,每个元素都是一个列表项。所以

    List<Object> emptyList = []
    List<Object> subList1 = [g,h,emptyList]
    List<Object> subList2 = [c,d,subList1]
    List<Object> subList3 = [a,b,c]
    List<Object> parentList = [sublist3,4,6,7,sublist2]

我只要求最后一个/父列表为上面的'parentList',中间结果可以忽略。
有人可以帮我用一个简洁的算法来解决这个问题。我已经尝试这样做了几个小时,但未能得出适当的递归调用方法解决方案。然而,非递归方法解决方案也最受欢迎:)

我已尝试使用以下代码。虽然,它有点粗糙。

    package com.psl.demo;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;

    public class ListClass {

        public List<Object> converToList(String string){
            List<Object> list = new ArrayList<Object>();

            string = string.trim();
            StringBuilder sb = new StringBuilder(string);

            List<Integer> startIndices= new ArrayList<Integer>();
            List<Integer> endIndices = new ArrayList<Integer>();

            int counter = 0;
            while(counter < sb.length()){
                if(sb.charAt(counter) == '{'){
                    startIndices.add(counter);
                    sb.setCharAt(counter, ' ');
                }
                counter++;
            }

            int reverseCounter = sb.length()-1;
            while(reverseCounter > 0){
                if(sb.charAt(reverseCounter) == '}'){
                    endIndices.add(reverseCounter);
                    sb.setCharAt(reverseCounter, ' ');
                }
                reverseCounter--;
            }

            if(startIndices.size() != endIndices.size()){
                System.out.println("Brackets do not match. exiting");
                System.exit(1);
            }


            int size = startIndices.size();
            counter = 0;
            reverseCounter = size-1;
            for(int i=0; i<size; i++){
                String contents =                 sb.substring(startIndices.get(reverseCounter), endIndices.get(counter));
                //sb.replace(startIndices.get(reverseCounter),         endIndices.get(counter),"");
                contents = contents.trim();
                List<Object> subList = new ArrayList<Object>();
                Object[] tokens = contents.split(",");
                for(int j=0; j< tokens.length;j++){
                    tokens[j] = tokens[j].toString().trim();
                }
                subList = Arrays.asList(tokens);
                list.add(subList);
                counter++;

                reverseCounter--;
            }

            Collections.reverse(list);
            return list;
        }

        public static void main(String[] args) {
            String string = "{{a ,b, {hello, world}},  4 ,6,  7, { c , d }         }";
            ListClass obj = new ListClass();
            List<Object> list= obj.converToList(string);
            System.out.println(list);
        }

    }

请忽略代码的 System.exit() 部分。这将被适当的代码取代。 由于我提到的特定要求,使用了对象类型列表。

【问题讨论】:

  • 那么您尝试了什么,什么问题阻碍了您?您迭代字符串的字符,提取值,并使用堆栈来跟踪当前正在构建的列表。不需要递归。
  • 拥有List&lt;Object&gt; 是个坏主意
  • 不应该输入给你一个编译错误。输入不是String
  • @Priyamal 它没有给出任何编译错误。输入字符串 'string' 是一个完全有效的字符串。
  • @Andreas 我已经添加了我尝试过的代码。你现在能帮帮我吗:)

标签: java string recursion arraylist nested


【解决方案1】:

这可能类似于 DS 中的表达式求值。所以我认为你需要使用 Stack 数据结构来解决这类问题。试试下面的代码,或许能解决你的问题。

package src.com;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Deque;
import java.util.List;
public class Abc {      
    public static class Bean {
        int token;
        Object obj;
        public Bean(){}
        public Bean(int token, Object o) {
            super();
            this.token = token;
            this.obj = o;
        }
    }
    public static void main(String[] args) {
        String input = "{{a,b,c},4, 6,7,{d,e,{},{ }}}";
        input = input.replaceAll(" ", "");
        List<Object> list = getList(input);
        System.out.println(list);
    }
    @SuppressWarnings("unchecked")
    public static List<Object> getList(String input1) {
        Deque<Object> stack = new ArrayDeque<Object>();
        char[] chararray = input1.toCharArray();
        String temp = "";
        for (int i = 0; i < chararray.length; i++) {
            if (chararray[i] == '}') {
                if (!temp.equals("")) {
                    stack.push(new Bean(0, temp));
                    temp = "";
                }
                List<Object> tmplist = new ArrayList<>();
                while (true) {
                    Object object = stack.pop();
                    if (object instanceof Bean) {
                        Bean b = (Bean) object;
                        if (b.token == 1)
                            break;
                        tmplist.add(b.obj);
                    } else {
                        tmplist.add(object);
                        if (stack.isEmpty())
                            break;
                    }
                }
                Collections.reverse(tmplist);
                stack.push(tmplist);
            } else {
                if (chararray[i] == '{') {
                    stack.push(new Bean(1, Character.toString(chararray[i])));
                } else if (chararray[i] == ',') {
                    if (!temp.equals("")) {
                        stack.push(new Bean(0, temp));
                        temp = "";
                    }
                } else {
                    temp = temp + Character.toString(chararray[i]);
                }
            }
        }
        return (List<Object>) stack.pop();
    }
}

【讨论】:

    【解决方案2】:

    您正在尝试做的事情看起来很像 JSON 反序列化。如果ab等用引号括起来,您可以使用Jackson

        import com.fasterxml.jackson.databind.ObjectMapper;
        // ...
        ObjectMapper jsonMapper = new ObjectMapper();
        String content = "{{\"a\",\"b\",\"c\"}, 4,6, 7 , {\"c\", \"d\", {\"g\", \"h\", {} }}}";
        String contentWithBrackets = content.replace('{', '[').replace('}',']');
        List list =  jsonMapper.readValue(contentWithBrackets, List.class);
        System.out.println(list); // [[a, b, c], 4, 6, 7, [c, d, [g, h, []]]]
    

    【讨论】:

    • 您提出了一个非常好的解决方案!非常感谢!但是,不允许在项目中使用任何外部 Jar。如果是的话,你的解决方案是最好的、简短的和清晰的 :)
    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 2012-08-31
    • 2012-07-22
    • 1970-01-01
    相关资源
    最近更新 更多