Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I replace multiple substrings with different substrings?

I have this line of chord obtained from text file. For example,

String chordLine = "C     G   Am  C";
String transposedChordLine;

Next, I need to transpose the chordLine into a new transposedChordLineusing the class below using two parameters, a String chord and integer increment of transpose. For example, transpose("C", 2) will return D.

 public class Transposer{
    private int inc;
    private static ArrayList<String> keysSharp;
    private static ArrayList<String> keysFlat;

    Transposer(){
        keysSharp = new ArrayList<String>(Arrays.asList("C", "C#", "D", "D#","E", "F","F#", "G","G#", "A","A#", "B"));
        keysFlat = new ArrayList<String>(Arrays.asList("C", "Db", "D", "Eb","E", "F","Gb", "G","Ab", "A","Bb", "B"));
    }

    public String transpose(String chord,int inc){

        this.inc = inc;

        String newChord;

        if(chord.contains("/")){
            String[] split = chord.split("/");
            newChord = transposeKey(split[0]) + "/" + transposeKey(split[1]);
        }else
            newChord = transposeKey(chord); 
        return newChord;
    }

    private String transposeKey(String key){ // C#m/D# must pass C#m or D#
        String nKey, tempKey;

        if(key.length()>1){ 
            nKey = key.substring(0, 2);
            }
        else{ nKey = key; }


        int oldIndex, newIndex;

        if(key.contains("b")){
            oldIndex = (keysFlat.indexOf(nKey)>-1) ? keysFlat.indexOf(nKey) : keysFlat.indexOf(similarKey(nKey));
            newIndex = (oldIndex + inc + keysFlat.size())%keysFlat.size();
            tempKey = keysFlat.get(newIndex);
            nKey = (key.length() < 3) ? tempKey : key.replace(nKey, tempKey);
                //(nKey + key.substring(nKey.length(), key.length()));
        }
        else if(key.contains("#")){
            oldIndex = (keysSharp.indexOf(nKey)>-1) ? keysSharp.indexOf(nKey) : keysSharp.indexOf(similarKey(nKey));
            newIndex = (oldIndex + inc + keysSharp.size())%keysSharp.size();
            tempKey = keysSharp.get(newIndex);
            nKey = (key.length() < 3) ? tempKey : key.replace(nKey, tempKey);
        }
        else{
            nKey = nKey.substring(0, 1);
            oldIndex = (keysSharp.indexOf(nKey)>-1) ? keysSharp.indexOf(nKey) : keysSharp.indexOf(similarKey(nKey));
            newIndex = (oldIndex + inc + keysSharp.size())%keysSharp.size();
            tempKey = keysSharp.get(newIndex);
            nKey = (key.length() < 2) ? tempKey : key.replace(nKey, tempKey);
        }



        return nKey;
    }


    private String similarKey(String nKey) {
        String newKey;
        switch(nKey){
        case "Cb":
            newKey = "B";
            break;
        case "Fb":
            newKey = "E";
            break;
        case "E#":
            newKey = "F";
            break;
        case "B#":
            newKey = "c";
            break;
        default:
            newKey = null;
        }
        return newKey;
    }
}

How do I replace the chordLine without losing the spaces? increment by 2 should have transposedChordLine="D A Bm D"

Here is my current attempt:

public static void main(String[] args) {

    String chordLine = "C      G            Am       C";
    String transposedChordLine;
    String normalize = chordLine.replaceAll("\\s+", " ");
    String[] split = normalize.split(" ");

    //System.out.println(normalize);


    Transposer tran = new Transposer();
    String[] temp = new String[split.length];

    for(int i=0 ; i<split.length ; i++){
        temp[i] = tran.transpose(split[i], 2);
        //System.out.println(split[i]);
        System.out.print(temp[i]);
    }

    transposedChordLine = chordLine.replaceAll([split], temp); //which is wrong

}
like image 924
Tuss Avatar asked Oct 31 '22 21:10

Tuss


1 Answers

Your tokenization is unusual enough (preserving delimiters), that you probably want to do it yourself. Basically, if you see a token that matches a note, pass it to the transposer. Otherwise, pass along a space. Use a while loop to navigate along the notes. Here's the code that does just that:

private static final Transposer transposer = new Transposer();

public static void main(String[] args) {
  String chordLine = "C      G            Am       C";

  String transposed = transposeChordLine(chordLine);

  System.out.println(transposed);
}

private static String transposeChordLine(String chordLine) {
  char[] chordLineArray = chordLine.toCharArray();

  StringBuilder transposed = new StringBuilder();
  StringBuilder currentToken = new StringBuilder();

  int index = 0;
  while(index < chordLine.length()) {
    if(chordLineArray[index] == ' ') {
      transposed.append(' ');
      currentToken = processToken(transposed, currentToken);
    } else {
      currentToken.append(chordLineArray[index]);
    }
    index++;
  }

  processToken(transposed, currentToken);

  return transposed.toString();
}

private static StringBuilder processToken(StringBuilder transposed,
    StringBuilder currentToken) {
  if(currentToken.length() > 0) {
    String currentChord = currentToken.toString();
    String transposedChord = transposer.transpose(currentChord, 2);
    transposed.append(transposedChord);
    currentToken = new StringBuilder();
  }
  return currentToken;
}

Note: you have some stylistic issues with your code. You can initialize your constant chord maps in the fields themselves; by doing so in the constructor, you overwrite them, doing unnecessary work and potentially causing problems, especially in multithreaded code. Just do them inline in the field declaration. It's also good to wrap these in Collections.unmodifiableList, so they can't be changed when your code is running and therefore it makes it easier to not accidentally make a mistake.

Also, you shouldn't save the inc variable in a field, just pass it through as an argument. This way, if you are using the same object twice, it doesn't preserve state and is therefore threadsafe. I know these things don't matter to your current program but it's good to learn these habits now. Here's the modified Transposer class:

public class Transposer {
  private static final List<String> keysSharp = Collections.unmodifiableList(Arrays.asList("C", "C#", "D", "D#", "E",
        "F", "F#", "G", "G#", "A", "A#", "B"));
  private static final List<String> keysFlat = Collections.unmodifiableList(Arrays.asList("C", "Db", "D", "Eb", "E",
      "F", "Gb", "G", "Ab", "A", "Bb", "B"));

  public String transpose(String chord, int inc) {
    String newChord;

    if (chord.contains("/")) {
      String[] split = chord.split("/");
      newChord = transposeKey(split[0], inc) + "/" + transposeKey(split[1], inc);
    } else
      newChord = transposeKey(chord, inc);
    return newChord;
  }

  private String transposeKey(String key, int inc) { // C#m/D# must pass C#m or D#
    String nKey, tempKey;

    if (key.length() > 1) {
      nKey = key.substring(0, 2);
    } else {
      nKey = key;
    }

    int oldIndex, newIndex;

    if (key.contains("b")) {
      oldIndex = (keysFlat.indexOf(nKey) > -1) ? keysFlat.indexOf(nKey)
          : keysFlat.indexOf(similarKey(nKey));
      newIndex = (oldIndex + inc + keysFlat.size()) % keysFlat.size();
      tempKey = keysFlat.get(newIndex);
      nKey = (key.length() < 3) ? tempKey : key.replace(nKey, tempKey);
      // (nKey + key.substring(nKey.length(), key.length()));
    } else if (key.contains("#")) {
      oldIndex = (keysSharp.indexOf(nKey) > -1) ? keysSharp.indexOf(nKey)
          : keysSharp.indexOf(similarKey(nKey));
      newIndex = (oldIndex + inc + keysSharp.size()) % keysSharp.size();
      tempKey = keysSharp.get(newIndex);
      nKey = (key.length() < 3) ? tempKey : key.replace(nKey, tempKey);
    } else {
      nKey = nKey.substring(0, 1);
      oldIndex = (keysSharp.indexOf(nKey) > -1) ? keysSharp.indexOf(nKey)
          : keysSharp.indexOf(similarKey(nKey));
      newIndex = (oldIndex + inc + keysSharp.size()) % keysSharp.size();
      tempKey = keysSharp.get(newIndex);
      nKey = (key.length() < 2) ? tempKey : key.replace(nKey, tempKey);
    }

    return nKey;
  }

  private String similarKey(String nKey) {
    String newKey;
    switch (nKey) {
    case "Cb":
      newKey = "B";
      break;
    case "Fb":
      newKey = "E";
      break;
    case "E#":
      newKey = "F";
      break;
    case "B#":
      newKey = "c";
      break;
    default:
      newKey = null;
    }
    return newKey;
  }
}
like image 150
durron597 Avatar answered Nov 15 '22 04:11

durron597