抽取ArrayList中的Java字符串数据,并使用I/O文件进行操作。

huangapple go评论82阅读模式
英文:

Abstracting Java Strings data from ArrayList and manipulating it using I/O files

问题

// PART 2: Separating musical notes and formatting
String notesLine = list.get(0); // Get the line with musical notes
String[] notesArray = notesLine.split("\\s+"); // Split by whitespace
List<String> formattedNotes = new ArrayList<>(); // To store the formatted notes

for (String note : notesArray) {
    if (!note.isEmpty()) { // Avoid empty strings
        formattedNotes.add(note + ","); // Add note with a comma
    }
}

// Combine the formatted notes into a single string
String formattedNotesLine = String.join(" ", formattedNotes);

// Add the formatted line to the printToFile ArrayList
printToFile.add(formattedNotesLine);

请注意,上述代码段是关于如何完成第二部分的解释和示例代码,这部分将音符分隔并进行格式化,以满足您的要求。将此代码段添加到您的项目中,确保与您的现有代码协同工作,并根据需要进行适当的调整。

请注意,由于您要求我只返回翻译好的部分,我已经从您的原始内容中提取了您想要的内容并进行了翻译。如果您有任何问题,欢迎随时提问。

英文:

I am a beginner. I am trying to learn 1) Read data from a file and store inside ArrayList 2) Manipulate String data 3) Output results to a new file using ArrayList. I have figured out Part 1 and Part 3 and I have provided the code. I am having problems manipulating strings. I am sure there is an easier solution but I am not able to see it even after spending many hours. I know I need to use either charAt(i) or note.substring() or both. Maybe a nested loop?

// Part 1 Reading notes from a file and storing it into ArrayList named list.
    BufferedReader bufReader = new BufferedReader(new FileReader(&quot;read1.txt&quot;));
    List&lt;String&gt; list = new ArrayList&lt;&gt;();
    String line = bufReader.readLine();
    while (line != null) {
        list.add(line);
        line = bufReader.readLine();
    }
    bufReader.close();
    list.forEach(System.out::println);//Print list to the Screen

    read1.txt  file   
    E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#
    C# E F# G# G# BAAG#   C# E F# G# C# B A G#

    May have lyrics here which needs to be avoided
    C# E G# C# B A G# G# B A G# F# A F# B G# F# D#

PART 2 This is where I'm having a problem. list[0] has many different musical notes with and without #. How do I sperate each note with "," so result would look something like following. I want to keep the format same. I don't want to remove the whitespaces.

    E,  F#,G#, F#,G#, E,   E,F#,D#, E, C#,    E, D#, C#, B,B,  C#,C#
    C#, E, F#, G#, G#, B,A,A,G#,   C#, E, F#, G#, C#, B, A, G#,

    May have lyrics here which needs to be avoided
    C#, E, G#, C#, B, A, G#, G#, B, A, G#, F#, A, F#, B, G#, F#, D#

I want to store above result into another ArrayList named printToFile and I want to output the result using following code.

//PART 3 This code will write List to a desired new file(write2.txt)
    List&lt;String&gt; printToFile = new ArrayList&lt;&gt;();
    //here We are assuming that results have been populated into printToFile
    BufferedWriter bufWriter = new BufferedWriter(new FileWriter(&quot;write2.txt&quot;));

    for (String wline : printToFile) {
        bufWriter.write(wline);
        bufWriter.newLine();
    }
    bufWriter.close();

Can someone pls teach me how to do Part2. I have tested Part1 and Part3. They work. For me, this is a learning tutorial so I will WELCOME different suggestions and ideas. Thanks

答案1

得分: 2

// lineToWrite will contain original whitespaces
String lineToWrite = String.join(",", buildListOfNotes(line));

// cleanLine will contain notes without extra spacing
String cleanLine = buildListOfNotes(line).stream()
                                         .map(String::trim)
                                         .collect(Collectors.joining(", "));
英文:

You may try replaceAll with a regular expression to replace each note [A-G] followed by optional # and removing trailing comma:

String line = &quot;E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#&quot;;
String str = line.replaceAll(&quot;([A-G]#?)&quot;, &quot;$1,&quot;);
if (str.endsWith(&quot;,&quot;)) {
    str = str.substring(0, str.length() - 1);
}
System.out.println(line);
System.out.println(str);

Output:

E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#
E,  F#,G#, F#,G#, E,   E,F#,D#, E, C#,    E, D#, C#, B,B,  C#,C#

note: if the input data contain other types of notes flat or sharp, the regular expression needs to be updated accordingly.

update<br/>
More advanced regular expression enables proper insertion of commas after each note except the last one (without removal of the trailing comma with additional code).

String str2 = line.replaceAll(&quot;([A-G]#?+(?!$))&quot;, &quot;$1,&quot;);
System.out.println(str2);

([A-G]#?+(?!$)):

  • 1st Capturing Group ([A-G]#?+(?!$))
    • Match a single character present in the list below [A-G]<br/>
      A-G a single character in the range between A (index 65) and G (index 71) (case sensitive)
    • #?+ matches the character # literally (case sensitive)<br/>
      ?+ Quantifier — Matches between zero and one times, as many times as possible, without giving back (possessive)
    • Negative Lookahead (?!$)<br/>
      Assert that the Regex below does not match<br/>
      $ asserts position at the end of a line

online demo

It also may be needed to verify if the given input string looks like a string of notes and then apply this modification to avoid inserting commas after single-letter words which might happen in the lyrics.

The matching regular expression is: ^(\s*[A-G]#?\s*)+$ - it checks if there is at least one note surrounded with optional whitespaces \s*.

So, the final solution would look like:

private static String insertCommasIfLineOfNotes(String line) {
    if (null == line || !line.matches(&quot;^(\\s*[A-G]#?\\s*)+$&quot;)) {
        return line;
    }
    return line.replaceAll(&quot;([A-G]#?+(?!$))&quot;, &quot;$1,&quot;);
}
// test
List&lt;String&gt; lines = Arrays.asList(
        &quot;E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#&quot;, 
        &quot;A Perfect Day Elise&quot;,
        &quot;A B C D E F G H I J K L M N O P&quot;
);
lines.stream()
     .map(MyClass::insertCommasIfLineOfNotes)
     .forEach(System.out::println);

// output
E,  F#,G#, F#,G#, E,   E,F#,D#, E, C#,    E, D#, C#, B,B,  C#,C#
A Perfect Day Elise
A B C D E F G H I J K L M N O P

update 2<br/>
If it is needed to get a list of substrings in the line of notes, containing plain notes A..G optionally followed by #, or sequences of 1 or more whitespaces, the following methods can be implemented.<br/>
refactored to add whitespace sequences to appropriate note entry to facilitate joining of the notes into single string

private static List&lt;String&gt; buildListOfNotes(String line) {
    if (null == line || !line.matches(&quot;^(\\s*[A-G]#?\\s*)+$&quot;)) {
        return Arrays.asList(line); // for lyrics line
    }
    List&lt;String&gt; result = new ArrayList&lt;&gt;();
      
    int spaceStart = -1;
    int spaceEnd = 0;
    for(int i = 0; i &lt; line.length() - 1; i++) {
        char c = line.charAt(i);
        boolean note = isNote(c);
        
        if (isNote(c)) {
            String prefix = &quot;&quot;;
            if (spaceStart &gt; -1) {
                // add existing whitespace as a prefix to current note
                int prevResult = result.size() - 1;
                prefix = line.substring(spaceStart, spaceEnd);
                spaceStart = -1;
            }
            if (line.charAt(i + 1) == &#39;#&#39;) {
                result.add(prefix + line.substring(i, i + 2));
                i++;
            } else {
                result.add(prefix + line.substring(i, i + 1));
                if (!isNote(line.charAt(i + 1))) {
                    spaceStart = i + 1;
                }
            }
        } else {
            if (spaceStart == -1) {
                spaceStart = i;
                spaceEnd = i + 1;
            } else {
                spaceEnd++;
            }
        }
      }
      if (spaceStart &gt; -1) {
          // add trailing whitespace if available to the last note
          int prevResult = result.size() - 1;
          result.set(prevResult, result.get(prevResult) + line.substring(spaceStart));
      }
      return result;
  }
  
  private static boolean isNote(char c) {
      return c &gt;= &#39;A&#39; &amp;&amp; c &lt;= &#39;G&#39;;
  }
// testing method to retrieve list of substring
List&lt;String&gt; lines = Arrays.asList(
        &quot;E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#&quot;,
        &quot;E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C#    &quot;,
        &quot;   E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C&quot;,
        &quot;   E  F#G# F#G# E   EF#D# E C#    E D# C# BB  C#C &quot;, 
        &quot;A Perfect Day Elise&quot;,
        &quot;A B C D E F G H I J K L M N O P&quot;
);
lines.stream()
     .map(MyClass::buildListOfNotes)
     .forEach(System.out::println);

Test output ("note" entry may include whitespace sequence):

[E,  F#, G#,  F#, G#,  E,   E, F#, D#,  E, C#,     E, D#,  C#,  B, B, C#, C#]
[E,  F#, G#,  F#, G#,  E,   E, F#, D#,  E, C#,     E, D#,  C#,  B, B, C#, C#    ]
[   E,  F#, G#,  F#, G#,  E,   E, F#, D#,  E, C#,     E, D#,  C#,  B, B, C#]
[   E,  F#, G#,  F#, G#,  E,   E, F#, D#,  E, C#,     E, D#,  C#,  B, B, C#, C ]
[A Perfect Day Elise]
[A B C D E F G H I J K L M N O P]

Then the array of notes can be easily converted into String using String.join:

// lineToWrite will contain original whitespaces
String lineToWrite = String.join(&quot;,&quot;, buildListOfNotes(line));

// cleanLine will contain notes without extra spacing
String cleanLine = buildListOfNotes(line).stream()
                                         .map(String::trim)
                                         .collect(Collectors.joining(&quot;, &quot;));

</details>



huangapple
  • 本文由 发表于 2020年10月6日 05:55:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/64216732.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定