2013-03-20 84 views
2

我正在做一些文本分析,并且需要在String中记录字符转换的频率。我有n字符类别:例如,isUpperCase()isNumber()isSpace()高效地比较字符串中的连续字符

鉴于有n类别,将有n^2过渡类别,例如, “isUpperCase() - >isUpperCase()”, “isUpperCase - >isLetter()”, “isLetter() - >isUpperCase()” 等

给定的文本块,我想记录所发生的转换数目。我会想象构建一个Map与过渡类型KeysInteger作为每个Value

对于文本“TO”的块中,Map看起来像[isUpper -> isUpper : 1, isUpper -> isSpace : 1]

的一部分,我想不通,不过,是如何构建一个Map这里,从我所看到的,Key将包括的2 boolean方法。

回答

4

创建一个代表字符类型的enum - 您需要一种方法来获取给定字符的字符类型enum。我确信有比下面做的更好的方法来做这件事,但这只是对读者的一个练习。

接下来创建一个方法,它将前一个字符和当前字符连接起来,并将它们的类型连接成一个唯一的String

最后循环输入字符串和嘿presto。

private static enum CharacterType { 

    UPPER { 
     @Override 
     boolean isA(final char c) { 
      return Character.isUpperCase(c); 
     } 
    }, 
    LOWER { 
     @Override 
     boolean isA(final char c) { 
      return Character.isLowerCase(c); 
     } 
    }, 
    SPACE { 
     @Override 
     boolean isA(final char c) { 
      return Character.isWhitespace(c); 
     } 
    }, 
    UNKOWN { 
     @Override 
     boolean isA(char c) { 
      return false; 
     } 
    }; 

    abstract boolean isA(final char c); 

    public static CharacterType toType(final char c) { 
     for (CharacterType type : values()) { 
      if (type.isA(c)) { 
       return type; 
      } 
     } 
     return UNKOWN; 
    } 
} 

private static String getTransitionType(final CharacterType prev, final CharacterType current) { 
    return prev + "_TO_" + current; 
} 

public static void main(String[] args) { 
    final String myString = "AAaaA Aaa AA"; 
    final Map<String, Integer> countMap = new TreeMap<String, Integer>() { 
     @Override 
     public Integer put(final String key, final Integer value) { 
      final Integer currentCount = get(key); 
      if (currentCount == null) { 
       return super.put(key, value); 
      } 
      return super.put(key, currentCount + value); 
     } 
    }; 
    final char[] myStringAsArray = myString.toCharArray(); 
    CharacterType prev = CharacterType.toType(myStringAsArray[0]); 
    for (int i = 1; i < myStringAsArray.length; ++i) { 
     final CharacterType current = CharacterType.toType(myStringAsArray[i]); 
     countMap.put(getTransitionType(prev, current), 1); 
     prev = current; 
    } 
    for (final Entry<String, Integer> entry : countMap.entrySet()) { 
     System.out.println(entry); 
    } 
} 

输出:

LOWER_TO_LOWER=2 
LOWER_TO_SPACE=1 
LOWER_TO_UPPER=1 
SPACE_TO_SPACE=1 
SPACE_TO_UPPER=2 
UPPER_TO_LOWER=2 
UPPER_TO_SPACE=1 
UPPER_TO_UPPER=2 

运行在你的问题的内容(825个字符)的方法把9ms的。

+0

首先,我只想说谢谢。我不知道这是否会工作,因为我需要更多地了解'enum',但它看起来很棒! – 2013-03-20 19:27:47

+0

这确实是一个非常优雅的解决方案。我喜欢! – loopkin 2013-03-21 17:35:00

0

如果你想大多数的过渡将存在,那么二维数组将最好的工作:

int n = _categories.size(); 
int[][] _transitionFreq = new int[n][n]; 

如果你认为这将是一个解析数组,然后地图将在条件更有效的内存使用率,但性能方面效率较低。

这是一个权衡,你必须根据你的数据和字符类型的数量。