2

我正在做一些文本分析,需要在String. 我有n类字符:例如isUpperCase(),、、isNumber()isSpace()

假设有n 个类别,就会有n^2 个类别的转换,例如“ isUpperCase()--> isUpperCase()”、“ isUpperCase--> isLetter()”、“ isLetter()--> isUpperCase()”等。

给定一段文本,我想记录发生的转换次数。我会想象构建一个Map过渡类型为 theKeys和一个Integeras each的 a Value

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

但是,我无法弄清楚的部分是如何构建一个Mapwhere,据我所知,Key它将由 2 个boolean方法组成。

4

2 回答 2

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 个字符)运行该方法需要 9 毫秒。

于 2013-03-20T12:33:56.613 回答
0

如果您认为大多数转换都会出现,那么二维数组效果最好:

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

如果您认为它将是一个解析数组,那么映射在内存使用方面会更有效,但在性能方面效率会更低。

根据您的数据和字符类型的数量,您必须做出权衡。

于 2013-03-20T12:45:15.983 回答