4

Using "Generating all permutations of a given string" as a reference, I am trying to get make my program (upon detecting the name field) write to the database all combinations of a name (the queryID aka qid is not a primary key. I intend for it all to be duplicate).

example: John Michael Doe

  1. John Michael Doe
  2. John Doe Michael
  3. Michael John Doe
  4. Michael Doe John
  5. Doe John Michael
  6. Doe Michael John

To give you a better idea of the scenario, when someone is using my program to search they can add "constraints".

Initial

So when they add a constraint they have a dropdown menu they can pick multiple categories and one of them is name.

After adding constraint

So if they input:
Name CONTAINS foo bar for the first constraint.
Id CONTAINS 1234 for the second constraint.
Name CONTAINS john doe for the last constraint.

It will create the SQL statement:
insert into qal.query_input values('df084b1f-1337','1234','','','foo bar john doe','','');
(the blank spaces are the categories that weren't searched for)

Now my issue is instead I would like this output (using the same search):

insert into qal.query_input values('df084b1f-1337','1234','','','foo bar','','');
insert into qal.query_input values('df084b1f-1337','1234','','','bar foo','','');
insert into qal.query_input values('df084b1f-1337','1234','','','john doe','','');
insert into qal.query_input values('df084b1f-1337','1234','','','doe john','','');

Currently this is my code:

ArrayList<String> fields = constraintToInputLogFieldMap.get(key);
ArrayList<String> names;
for (String field : fields) {
    ArrayList<String> values = inputLogFieldValues.get(field);

    if (values == null) {
        values = new ArrayList<>();
        inputLogFieldValues.put(field, values);
    }

    // only retrieve singletonRange and listRange          
    if (singletonRange != null) {
        values.add((String) singletonRange.getValue());
    }
    if (listRange != null) {
        for (Object v : listRange.getValues()) {
            values.add((String) v);
        }
    }
}
// This creates an arrayList for each name
// ie. [foo bar, john doe]
names = inputLogFieldValues.get("Name");

for (String field : inputLogFields) {
    ArrayList<String> values = inputLogFieldValues.get(field);
    if (values == null)
        inputEntry += ",''";
    else {
        String valueStr = "";
        for (String value : values)
            valueStr += " " + value;
        inputEntry += ",'" + valueStr.substring(1) + "'";
    }
}
inputEntry = "insert into qal.query_input values('" + qid + "'" + inputEntry + ");";
logger.info("Stackoverflow SQL output: " + inputEntry);
dbUpdate(inputEntry);

Now my question is the algorithm on how to do this when the input for the arraylist is unknown? (the amount of constraints and length of names ie. firstname middlename lastname secondlastname)

If anything needs clarifying or I need to input more of my code just tell me.

UPDATE 2/10/2016 17:36EST

I modified the bottom part of my code and it now separates each name (instead of combining into one) while still preserving the other fields.

Output Before:
insert into qal.query_input values('df084b1f-1337','1234','','','foo bar john doe','','');
Output with Update:
insert into qal.query_input values('df084b1f-1337','1234','','','foo bar','','');
insert into qal.query_input values('df084b1f-1337','1234','','','john doe','','');

Updated Code (such a simple change):

ArrayList<String> inputEntries = new ArrayList<>();
for (String name : names) {
    inputEntry = "";
    for (String field : inputLogFields) {
        ArrayList<String> values = inputLogFieldValues.get(field);
        if (values == null)
            inputEntry += ",''";
        else {
            if (field.equals("Name")) {
                inputEntry += ",'" + name + "'";
            } else {
                String valueStr = "";
                for (String value : values)
                    valueStr += " " + value;
                inputEntry += ",'" + valueStr.substring(1) + "'";
            }
        }
    }
    inputEntry = "insert into qal.query_input values('" + qid + "'" + inputEntry + ");";
    inputEntries.add(inputEntry);
}
for (String sqlEntry : inputEntries) {
    dbUpdate(sqlEntry);
}

Now the only problem I have left to figure out is a way to generate the name permutations.

Community
  • 1
  • 1
Joey
  • 1,724
  • 3
  • 18
  • 38

1 Answers1

0

Using "Generating all possible permutations of a list recursively" as a reference I added/changed this small section.

ArrayList<String> inputEntries = new ArrayList<>();
ArrayList<String> permutedNames = names; // <----
for (String name : permutedNames) { // <--- Now permutedNames
    inputEntry = "";
    for (String field : inputLogFields) { ...

And added the following functions:

private ArrayList<String> splitNames(ArrayList<String> listOfNames) {
    String temp = "";
    List<String> splitName;
    List<List<String>> listSplitName = new ArrayList<List<String>>();
    ArrayList<String> toReturn = new ArrayList<String>();

    if (listOfNames.size() == 1) {
        temp = listOfNames.get(0);
        splitName =  new ArrayList<String>(Arrays.asList(temp.split(" ")));
        listSplitName = generatePerm(splitName);
        for (int i = 0; i < listSplitName.size(); i++) {
            toReturn.add(listSplitName.get(i).toString());
        }
        return toReturn;
    }
    else {
        for (int i = 0; i < listOfNames.size(); i++) {
            temp = listOfNames.get(i);
            splitName = new ArrayList<String>(Arrays.asList(temp.split(" ")));
            listSplitName = generatePerm(splitName);
            for (int j = 0; j < listSplitName.size(); j++) {
                toReturn.add(listSplitName.get(j).toString());
            }
        }
        return toReturn;
    }
}

private List<List<String>> generatePerm(List<String> original) {
    if (original.size() == 0) {
        List<List<String>> result = new ArrayList<List<String>>();
        result.add(new ArrayList<String>());
        return result;
    }
    String firstElement = original.remove(0);
    List<List<String>> returnValue = new ArrayList<List<String>>();
    List<List<String>> permutations = generatePerm(original);
    for (List<String> smallerPermutated : permutations) {
        for (int index=0; index <= smallerPermutated.size(); index++) {
            List<String> temp = new ArrayList<String>(smallerPermutated);
            temp.add(index, firstElement);
            returnValue.add(temp);
        }
    }
    return returnValue;
}

The splitNames function takes a list of names and breaks each name into a separate array with just the names.

example:
input - [John Doe, Foo Bar Bat] output - [John, Doe] gets sent to generatePerm and [Foo, Bar, Bat] gets sent to generatePerm

Then generatePerm will permutate each one and sends back a list of combinations.

This is then sent back into splitNames which will compile the permutations into an ArrayList and return it back.

Community
  • 1
  • 1
Joey
  • 1,724
  • 3
  • 18
  • 38