使用split方法以最有效的方式导出特定的字符串模式

时间:2013-12-30 08:12:19

标签: java string methods pattern-matching

我想在String varilable中导出位流模式。假设我们的比特流类似于bitStream =“111000001010000100001111”。我正在寻找一个Java代码来保存这个位流在一个特定的数组(假设bitArray)中,所有连续的“0”或“1”都保存在一个数组元素中。在这个例子中,输出将是这样的东西:

bitArray[0]="111"
bitArray[1]="00000"
bitArray[2]="1"
bitArray[3]="0"
bitArray[4]="1"
bitArray[5]="0000"
bitArray[6]="1"
bitArray[7]="0000"
bitArray[8]="1111"

我想使用bitArray来计算每个连续流中存储的位数。例如,在这种情况下,最终输出将是“3,5,1,1,1,4,1,4,4”。我弄清楚可能“拆分”方法会为我解决这个问题。但是我不知道分裂模式会对我做什么,如果我使用bitStream.split("1+")它将分裂为连续的“1”模式,如果我使用bitStream.split("0+")它将基于连续的“0”进行它是如何基于两者的?

Mathew提出了这个解决方案并且有效:

var wholeString = "111000001010000100001111";
wholeString = wholeString.replace('10', '1,0');
wholeString = wholeString.replace('01', '0,1');
stringSplit = wholeString.split(',');

我的问题是“此解决方案是最有效的吗?”

7 个答案:

答案 0 :(得分:3)

尝试分别用“0,1”和“1,0”替换任何出现的“01”和“10”。然后,一旦注入了逗号,就使用逗号分隔字符串作为分隔符。

String wholeString = "111000001010000100001111"

wholeString = wholeString.replace("10", "1,0");
wholeString = wholeString.replace("01", "0,1");

String stringSplit[] = wholeString.split(",");

答案 1 :(得分:2)

您可以使用简单的正则表达式执行此操作。它匹配1和0,并将按照它们在流中出现的顺序返回每个。您如何存储或操作结果取决于您。这是一些示例代码。

String testString = "111000001010000100001111";

Pattern pattern = Pattern.compile("1+|0+");
Matcher matcher = pattern.matcher(testString);

while (matcher.find())
{
    System.out.print(matcher.group().length());
    System.out.print(" ");
}

这将产生以下输出:

3 5 1 1 1 4 1 4 4

存储结果的一个选项是将它们放在ArrayList<Integer>

由于OP希望效率最高,我做了一些测试,看看每个答案在一次大流上迭代10000次需要多长时间,并得出以下结果。在每次测试中,时间不同,但最快到最慢的顺序保持不变。我知道刻度性能测试有没有考虑系统负载的问题,但我只是想快速测试。

My answer completed in 1145 ms
Alessio's answer completed in 1202 ms
Matthew Lee Keith's answer completed in 2002 ms
Evgeniy Dorofeev's answer completed in 2556 ms

希望这有帮助

答案 2 :(得分:1)

我不会给你一个代码,但我会引导你找到一个可能的解决方案:

构造一个ArrayList<Integer>,迭代位数组,只要你有1,递增一个计数器,只要你有0,就把计数器添加到ArrayList 。完成此程序后,您将拥有一个包含数字等的ArrayList:[1,2,2,3,4] - 代表1和0的系列。
这将代表1&0和0的序列。然后构造一个大小为ArrayList数组,并相应地填充它。

时间复杂度为O(n),因为您只需要对数组进行一次迭代。

答案 3 :(得分:1)

此代码适用于任何字符串和模式,而不仅仅是1和0。通过char迭代char,如果当前char等于前一个char,则将最后一个char附加到List的最后一个元素,否则在列表中创建一个新元素。

public List<String> getArray(String input){

    List<String> output = new ArrayList<String>();
    if(input==null || input.length==0) return output;
    int count = 0;
    char [] inputA = input.toCharArray();
    output.add(inputA[0]+"");
    for(int i = 1; i <inputA.length;i++){
        if(inputA[i]==inputA[i-1]){
            String current = output.get(count)+inputA[i];
            output.remove(count);
            output.add(current);
        }
        else{
            output.add(inputA[i]+"");
            count++;
        }
    }
    return output;
}

答案 4 :(得分:1)

试试这个

    String[] a = s.replaceAll("(.)(?!\\1)", "$1,").split(",");

答案 5 :(得分:1)

我试图实施@Maroun Maroun解决方案。

public static void main(String args[]){
    long start = System.currentTimeMillis();
    String bitStream ="0111000001010000100001111";
    int length = bitStream.length();
    char base = bitStream.charAt(0);
    ArrayList<Integer> counts = new ArrayList<Integer>();
    int count = -1;
    char currChar = ' ';
    for (int i=0;i<length;i++){
        currChar = bitStream.charAt(i);
        if (currChar == base){
            count++;
        }else {
            base = currChar;
            counts.add(count+1);
            count = 0;
        }
    }
    counts.add(count+1);
    System.out.println("Time taken :" + (System.currentTimeMillis()-start ) +"ms");
    System.out.println(counts.toString());
}

我认为这是更有效的方式,因为他说它是O(n),你只迭代一次。因为获取计数的目标只是不将它存储为数组。我想推荐这个。即使我们使用正则表达式(内部也必须以任何方式迭代)

结果输出是

Time taken :0ms
[1, 3, 5, 1, 1, 1, 4, 1, 4, 4]

答案 6 :(得分:0)

试试这个:

String[] parts = input.split("(?<=1)(?=0)|(?<=0)(?=1)");

请点击此处:http://rubular.com/r/qyyfHNAo0T