Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何用不同的子字符串替换多个子字符串?_Java_String_Replace - Fatal编程技术网

Java 如何用不同的子字符串替换多个子字符串?

Java 如何用不同的子字符串替换多个子字符串?,java,string,replace,Java,String,Replace,我从文本文件中获得了这行和弦。比如说, String chordLine = "C G Am C"; String transposedChordLine; 接下来,我需要使用下面的类,使用两个参数将弦线转换为一个新的转换弦线,一个字符串和弦和转置的整数增量。例如,转置(“C”,2)将返回D public class Transposer{ private int inc; private static ArrayList<String> keysS

我从文本文件中获得了这行和弦。比如说,

String chordLine = "C     G   Am  C";
String transposedChordLine;
接下来,我需要使用下面的类,使用两个参数将
弦线
转换为一个新的
转换弦线
,一个
字符串
和弦和转置的整数增量。例如,
转置(“C”,2)
将返回
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;
    }
}

您的标记化非常不寻常(保留分隔符),因此您可能希望自己进行标记化。基本上,如果您看到与音符匹配的标记,请将其传递给转发器。否则,沿空间传递。使用while循环沿注释导航。下面是实现这一点的代码:

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;
}
以下是较短的解决方案(我将此方法添加到
Transposer
类中):

我正在使用正则表达式匹配器创建新字符串。正则表达式匹配和弦名称以及其后的所有空格。为了确保替换具有相同的长度,我使用
String.format
并提供类似
%-XXs
的格式字符串,其中
XX
是带空格的未转置和弦的长度。请注意,如果没有足够的空间,则生成的线将变长

用法:

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

    System.out.println(chordLine);
    for(int i=0; i<12; i++) {
        String result = new Transposer().transposeLine(chordLine, i);
        System.out.println(result);
    }
}

给定弦线、转置器和转置增量:

String chordLine = "C      G            Am       C";
Transposer tran = new Transposer();
int offset = 2;
要在保留空白的同时获得转置的和弦线,可以使用在空白边界处分割,然后通过转置器有条件地处理结果字符串,如下所示:

String transposed = Arrays.stream(chordLine.split("((?<=\\s)|(?=\\s))")).map(  // use regex to split on every whitespace boundary
    str ->                                                                          // for each string in the split
        Character.isWhitespace(str.charAt(0))                                       // if the string is whitespace
            ? str                                                                   // then keep the whitespace
            : tran.transpose(str, offset)                                           // otherwise, it's a chord, so transpose it
).collect(Collectors.joining());                                                    // re-join all the strings together

很多潜在的解决方案。例如:创建一个对象,
弦线
,它将引用一条弦线。在该对象的构造函数中,可以显式跟踪和弦
n_i
n_i+1
之间的空白量。然后,在换位时,您可以简单地替换输出
弦线中的空白
对不起,这与您的问题无关,但您的代码非常糟糕。不要初始化构造函数中的
静态
成员。将两个static更改为
List
,并直接使用
Arrays.asList
初始化它们。另外,不要使用实例字段将参数传递给私有方法。如果调用
transpose
inc
可以不同,则将其作为参数传递给私有方法。如果
inc
总是相同的,那么将其传递给构造函数,而不是
transpose
方法。谢谢你的评论。
public static void main(String[] args) {
    String chordLine = "C      G            Am       C";

    System.out.println(chordLine);
    for(int i=0; i<12; i++) {
        String result = new Transposer().transposeLine(chordLine, i);
        System.out.println(result);
    }
}
C      G            Am       C
C      G            Am       C
C#     G#           A#m      C#
D      A            Bm       D
D#     A#           Cm       D#
E      B            C#m      E
F      C            Dm       F
F#     C#           D#m      F#
G      D            Em       G
G#     D#           Fm       G#
A      E            F#m      A
A#     F            Gm       A#
B      F#           G#m      B
String chordLine = "C      G            Am       C";
Transposer tran = new Transposer();
int offset = 2;
String transposed = Arrays.stream(chordLine.split("((?<=\\s)|(?=\\s))")).map(  // use regex to split on every whitespace boundary
    str ->                                                                          // for each string in the split
        Character.isWhitespace(str.charAt(0))                                       // if the string is whitespace
            ? str                                                                   // then keep the whitespace
            : tran.transpose(str, offset)                                           // otherwise, it's a chord, so transpose it
).collect(Collectors.joining());                                                    // re-join all the strings together
StringBuilder sb = new StringBuilder();
for (String str : chordLine.split("((?<=\\s)|(?=\\s))")) {
    sb.append(Character.isWhitespace(str.charAt(0)) ? str : tran.transpose(str, offset));
}
String transposed = sb.toString();