繁体   English   中英

如何从字符串中分离出许多不同的单词(Java)

[英]How to separate many different words from a string (Java)

我一直在努力弄清楚如何从长度未知的字符串中获取一个未知长度的单词,我正在从文件中读取。 我希望字符串中的单词始终用“。”分隔。 和/或“&”,整个字符串被引号括起来。 EX:“。Word.Characters&Numeric&Letters.Typos&Mistypes。” 我知道每个“。”的位置。 和“&”以及它们发生的次数。

我想根据单词是否用“。”分隔,将单词输入数组Example [i] [j]。 或“和”。 所以“。”之间包含的单词。 将被设置到数组的i列和由“&”链接到数组的j行的单词。

输入字符串可以包含很多可变数量的单词。 意思是只能有一个感兴趣的词,或者一百个+。

我更喜欢使用数组来解决这个问题。 从我所看到的正则表达式将是缓慢的,但工作。 split()也可以工作,但我想我必须知道要事先找哪些字。

从这个字符串:“。Word.Characters&Numeric&Letters.Typos&Mistypes。” 我希望得到:(不用担心哪一行或一列)

[[字],[空],[空],

[[性状],[数字],[信件]]

[[错别字],[输入错误],[空]]

从这个字符串“.Alpha.Beta.Zeta&Iota。” 我希望得到:

[α],[空],

[β],[空],

[[泽塔],[IOTA]]

//NumerOfPeriods tells me how many word "sections" are in the string
//Stor[] is an array that holds the string index locations of "."
for(int i=0;i<NumberOfPeriods;i++)
{
    int length = Stor[i];
    while(Line.charAt(length) != '"')
    {
        length++;
    }
    Example[i] = Line.substring(Stor[i], length);
}
//This code can get the words separated by "." but not by "&"

//Stor[] is an array that holds all string index locations of '.'
//AmpStor[] is an array that holds all string index locations of '&'
int TotalLength = Stor[0];
int InnerLength = 0;
int OuterLength = 0;
while(Line.charAt(TotalLength) != '"')
{
    while(Line.charAt(OuterLength)!='.')
    {
        while(Line.charAt(InnerLength)!='&')
        {
            InnerLength++;
        }
        if(Stor[i] > AmpStor[i])
        {
            Example[i][j] = Line.substring(Stor[i], InnerLength);
        }
        if(Stor[i] < AmpStor[i])
        {
            Example[i][j] = Line.substring(AmpStor[i],InnerLength);
        }
            OuterLength++;
    }
}
//Here I run into the issue of indexing into different parts of the array i & j

这就是我如何解决你的问题(它与你的代码完全不同,但它有效)。

首先,删除引号以及前导和尾随非单词字符。 这可以使用replaceAll来完成:

String Formatted = Line.replaceAll( "(^\"[.&]*)|([.&]*\"$)", "" );

第一个参数中的正则表达式将匹配两端的双引号以及前导和尾随. s和& s。 该方法将返回一个删除匹配字符的新字符串,因为第二个参数是一个空字符串(它替换为空字符串)。

现在,您可以拆分此字符串在每个. 使用split方法。 您只能在此调用后定义输出数组:

String[] StringGroups = Formatted.split( "\\." );
String[][] Elements = new String[StringGroups.length][];

在该点之前使用转义反斜杠( \\\\ )表示它应该拆分. -characters,因为此方法接受正则表达式(并且只是.在任何非换行符上拆分)。

现在将每个字符串中的每个字符串拆分&使用相同的split方法。 将结果直接添加到Elements数组:

// Loop over the array
int MaxLength = 0;
for( int i = 0; i < StringGroups.length; i ++ ) {
   String StrGroup = StringGroups[ i ];
   String[] Group = StrGroup.split( "&" );
   Elements[ i ] = Group;

   // Measure the max length
   if( Group.length > MaxLength ) {
       MaxLength = Group.length;
   }
}

输入不需要\\\\ ,因为&只匹配& -characters。 现在,您只需将数据填入数组即可。 MaxLength变量用于将null值添加到数组中。 如果你不想要它们,只需删除它们就可以了。

但是,如果您想要null值,请遍历您的elements数组并将当前行复制到新数组中:

for( int i = 0; i < Elements.length; i ++ ) {
    String[] Current = Elements[ i ];
    String[] New = new String[ MaxLength ];

    // Copy existing values into new array, extra values remain null
    System.arraycopy( Current, 0, New, 0, Current.length );
    Elements[ i ] = New;
}

现在, Elements数组包含您想要的内容。

这是完整的可执行代码:

public class StringSplitterExample {
    public static void main( String[] args ) {
        test( "\".Word.Characters&Numeric&Letters.Typos&Mistypes.\"" );
        System.out.println(); // Line between
        test( "\".Alpha.Beta.Zeta&Iota.\"" );
    }

    public static void test( String Line ) {
        String Formatted = Line.replaceAll( "(^\"[.&]*)|([.&]*\"$)", "" );
        String[] StringGroups = Formatted.split( "\\." );
        String[][] Elements = new String[StringGroups.length][];

        // Loop over the array
        int MaxLength = 0;
        for( int i = 0; i < StringGroups.length; i ++ ) {
            String StrGroup = StringGroups[ i ];
            String[] Group = StrGroup.split( "&" );
            Elements[ i ] = Group;

            // Measure the max length
            if( Group.length > MaxLength ) {
                MaxLength = Group.length;
            }
        }

        for( int i = 0; i < Elements.length; i ++ ) {
            String[] Current = Elements[ i ];
            String[] New = new String[ MaxLength ];

            // Copy existing values into new array, extra values remain null
            System.arraycopy( Current, 0, New, 0, Current.length );
            Elements[ i ] = New;
        }

        for( String[] Group : Elements ) {
            for( String String : Group ) {
                System.out.print( String );
                System.out.print( " " );
            }
            System.out.println();
        }
    }
}

这个例子的输出:

Word null null 
Characters Numeric Letters 
Typos Mistypes null 

Alpha null 
Beta null 
Zeta Iota

所以这个工作,你甚至不需要知道在哪里. &字符在你的字符串中。 Java将为您做到这一点。

如果我正确理解了问题,您希望将字符串分隔为由'。'分隔的子字符串。 然后对于每个子串,将其分成由'&'分隔的子子串。 如果是这种情况,那么我会使用split方法:

List<List<String>> terms = Arrays.stream(input.split("\\."))
    .map(s -> Arrays.asList(s.split("\\&"))
    .collect(Collectors.toList());

如果你真的需要它作为空填充数组返回:

String[][] result = new String[terms.size()][ terms.stream.mapToInt(List::size).max().getAsInt()];
IntStream.range(0, terms.size()).forEach(i ->
    IntStream.range(0, terms.get(i).size()).forEach(j -> 
        result[i][j] = terms.get(i).get(j)));

以下是我尝试解决问题的方法:

import java.util.*;
import java.util.stream.*;

public class StringSplitSplits {

    private static final String S1 = ".Word.Characters&Numeric&Letters.Typos&Mistypes.";
    private static final String S2 = ".Alpha.Beta.Zeta&Iota.";

    public static void main(String [] args) {

        String str = stripStartAndEndDots(S1);
        String [] ss = str.split("\\.");
        int maxLength = getMaxLength(ss);

        String [][] sss = Stream.of(ss)
                                .map(s -> s.split("&"))
                                .map(s -> Arrays.copyOf(s, maxLength))
                                .toArray(String[][]::new);
        Stream.of(sss).forEach(s -> System.out.println(Arrays.toString(s)));
    }

    private static String stripStartAndEndDots(String input) {
        if (input.startsWith(".")) {
            input = input.substring(1);
        }
        if (input.endsWith(".")) {
            input = input.substring(0, input.length()-1);
        }
        return input;
    }

    /*
     * Get max length of the arrays split on the "&" for each
     * string element of the input string array.
     */
    private static int getMaxLength(String [] input) {
        return Stream.of(input)
                        .map(s -> s.split("&"))
                        .mapToInt(ss -> ss.length)
                        .max()
                        .orElse(0);
    }
}


输入: ".Word.Characters&Numeric&Letters.Typos&Mistypes."
输出:

[Word, null, null]
[Characters, Numeric, Letters]
[Typos, Mistypes, null]

输入: ".Alpha.Beta.Zeta&Iota."
输出:

[Alpha, null]
[Beta, null]
[Zeta, Iota]

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM