Есть ли способ автоматизировать генерацию динамического кода в Java? - PullRequest
1 голос
/ 28 октября 2019

Мне нужно что-то в моем коде, которое будет динамически генерировать циклы и соответствующее им тело. Мой код сейчас выглядит так, для которого я явно определил каждый цикл и тело цикла, каждый из которых выполняется на основе значения переменной "len". Как я могу изменить его так, чтобы коды циклов, например, те, которые я написал для каждого условия, генерировались динамически?

ArrayList<String> mapAll(String input){
        int len = input.length();
        ArrayList<String> outputs= new ArrayList<>();
        //String[] outputs = new String[len];
        ArrayList<String> outputStrings= new ArrayList<>();
        for (int i = 0; i <len ; i++)
            outputs.add(mapOne(Character.toString(input.charAt(i))));

        if (len == 1)
            for (int i = 0; i <outputs.get(len -1).length() ; i++)
                    outputStrings = outputs;

        else if (len == 2)
            for (int i = 0; i <outputs.get(len-2).length() ; i++)
                for (int j = 0; j < outputs.get(len - 1).length(); j++)
                    outputStrings.add(Character.toString(outputs.get(len - 2).charAt(i)) + outputs.get(len - 1).charAt(j));



        else if(len == 3)
            for (int i = 0; i <outputs.get(len-3).length(); i++)
                for (int j = 0; j <outputs.get(len-2).length(); j++)
                    for (int k = 0; k <outputs.get(len-1).length(); k++)
                        outputStrings.add(Character.toString(outputs.get(len-3).charAt(i)) + outputs.get(len - 2).charAt(j) + outputs.get(len - 1).charAt(k));


        else if(len==4)
            for (int i = 0; i < outputs.get(len-4).length(); i++)
                for(int j = 0; j < outputs.get(len-3).length(); j++)
                    for(int k = 0; k < outputs.get(len-2).length(); k++)
                        for(int l = 0; l < outputs.get(len-1).length(); l++)
                            outputStrings.add(Character.toString(outputs.get(len-4).charAt(i)) + outputs.get(len-3).charAt(j) + outputs.get(len-2).charAt(k)+ outputs.get(len-1).charAt(l));


        return outputStrings;
    }

Реализация метода mapOne:

   private String mapOne(String in){
        String out;
        switch (in){
            case "a":
                out = "a"+"q"+"w"+"s"+"z";
                break;
            case "b":
                out = "b"+"g"+"h"+"v"+"n"+" ";
                break;
            case "c":
                out = "c"+"d"+"f"+"x"+"v"+" ";
                break;
            case "d":
                out = "d"+"e"+"r"+"s"+"f"+"x"+"c";
                break;
            case "e":
                out = "e"+"w"+"r"+"s"+"d";
                break;
            case "f":
                out = "f"+"r"+"t"+"d"+"g"+"c"+"v";
                break;
            case "g":
                out = "g"+"t"+"y"+"f"+"h"+"v"+"b";
                break;
            case "h":
                out = "h"+"y"+"u"+"g"+"j"+"b"+"n";
                break;
            case "i":
                out = "i"+"u"+"o"+"j"+"k";
                break;
            case "j":
                out = "j"+"u"+"i"+"h"+"k"+"n"+"m";
                break;
            case "k":
                out = "k"+"i"+"o"+"j"+"l"+"m";
                break;
            case "l":
                out = "l"+"o"+"p"+"k";
                break;
            case "m":
                out = "m"+"j"+"k"+"n"+" ";
                break;
            case "n":
                out = "n"+"h"+"j"+"b"+"m"+" ";
                break;
            case "o":
                out = "o"+"i"+"p"+"k"+"l";
                break;
            case "p":
                out = "p"+"o"+"l";
                break;
            case "q":
                out = "q"+"w"+"a";
                break;
            case "r":
                out = "r"+"e"+"t"+"d"+"f";
                break;
            case "s":
                out = "s"+"w"+"e"+"a"+"d"+"z"+"x";
                break;
            case "t":
                out = "t"+"r"+"y"+"f"+"g";
                break;
            case "u":
                out = "u"+"y"+"i"+"h"+"j";
                break;
            case "v":
                out = "v"+"f"+"g"+"c"+"b"+" ";
                break;
            case "w":
                out = "w"+"q"+"e"+"a"+"s";
                break;
            case "x":
                out = "x"+"s"+"d"+"z"+"c"+" ";
                break;
            case "y":
                out = "y"+"t"+"u"+"g"+"h";
                break;
            case "z":
                out = "z"+"a"+"s"+"x";
                break;
            case " ":
                out = " "+"x"+"c"+"v"+"b"+"n"+"m";
                break;
            default:
                out = "#";


        }
        return out;
    }

1 Ответ

1 голос
/ 28 октября 2019

Чистая версия с потоками:

static ArrayList<String> mapAll1(String input) {
    int len = input.length();
    ArrayList<String> outputs = new ArrayList<>();
    //String[] outputs = new String[len];
    ArrayList<String> outputStrings = new ArrayList<>();
    for (int i = 0; i < len; i++)
        outputs.add(mapOne(Character.toString(input.charAt(i))));

    if (len == 1)
        for (int i = 0; i < outputs.get(len - 1).length(); i++)
            outputStrings = outputs;

    else {
        outputStrings = IntStream
                .range(0, len)
                // get last n strings from outputs, starts from last
                .mapToObj(i -> outputs.get(len - (i + 1)))
                // transform List<String> into List<List<String>>,
                .map(x -> new ArrayList<>(x.chars()
                        .mapToObj(Character::toString)
                        .collect(Collectors.toList()))
                )
                // reduce
                .reduce(new ArrayList<>(), (acc, list) -> new ArrayList<>(
                        acc.isEmpty() ? list : list.stream()
                                .flatMap(prefix -> acc.stream()
                                        .map(tail -> prefix + tail)
                                ).collect(Collectors.toList())));
    }

    return outputStrings;
}

Основная часть написана по-старому с дальнейшим объяснением

if (len == 1)
    for (int i = 0; i < outputs.get(len - 1).length(); i++)
        outputStrings = outputs;

else {
    ArrayList<ArrayList<String>> tokenizeStrings = new ArrayList();
    // get last n strings from outputs, starts from last
    for (int i = 0; i < len; i++) {
        // transform List<String> into List<List<String>>,
        tokenizeStrings.add( new ArrayList<>(outputs.get(len - (i + 1)).chars()
                .mapToObj(Character::toString)
                .collect(Collectors.toList())));
    }

    outputStrings = new ArrayList<>();
    // reduce
    for (ArrayList<String> list: tokenizeStrings) {
        if (outputStrings.isEmpty()) {
            // first iteration just makes a copy
            outputStrings = list;
        } else {
            ArrayList<String> temp = new ArrayList<>();
            for (String prefix : list) {
                // for the rest iterations use string 'prefix' from current list
                // and add it in front of every string from main list 'outputStrings'
                for (String tail : outputStrings) {
                    temp.add(prefix + tail);
                }
            }
            // replace outputStrings with temp list
            outputStrings = temp;
        }
    }
}

return outputStrings;
...