【问题标题】:java calculating number of bigrams in stringjava计算字符串中的二元组数
【发布时间】:2019-03-15 18:06:22
【问题描述】:

我有以下方法可以创建二元输入。我需要计算二元组的数量来计算每次出现的概率。

public static String sortCountBigrams(ArrayList<String> bigrams) {
    String outputResult = "";
    Collections.sort(bigrams);
    String curr = bigrams.get(0);
    int counter = 1;
    for (String next : bigrams) {
        if (next.equals(curr)) {
            counter++;
        } else {
            outputResult += curr + " " + Double.toString(counter) + " ";
            counter = 1;
            curr = next;
        }
    }
    return outputResult; 

}

这是二元组的示例输出,如下所示:

af 22 ag 22 ah 7 ai 53 aj 74 ak 1 al 384 am 157

我需要将计算(如下)添加到方法中,java 库中是否有一个函数可以在二元组中的元素数量不是常数的情况下执行此操作。

af 22/8 ag 22/8 ah 7/8 ai 53/8 aj 74/8 ak 1/8 al 384/8 am 157/8

提前致谢。

【问题讨论】:

  • 这真的是你计算概率的方式。例如。 22/8、384/8。您确实意识到它永远不会大于 1。也许您正在寻找 22/(22+22+7+53+74+1+384+157) 等等?
  • 您的第一句话是正确的。大多数概率将远小于 1。这就是我的目标。
  • 您可以通过将列表中的元素数 (16) 除以 2 来获得分隔符
  • 有计算元素个数的函数吗?这不是一个常数。 @Bentaye
  • 只是澄清一下,af 22 ag 22 ah 7 ai 53 aj 74 ak 1 al 384 am 157 是输入列表吗?如果没有,你从哪里得到这些数字?

标签: java


【解决方案1】:

拳头可以收集每个二元组的计数:

Map<String, Long> counts = bigrams().stream()
    .collect(Collectors.groupingBy(Function.identity(), Collectors.counting());
double denominator = counts.size(); // Really not bigrams.size()?

根据要求,我已将分母设置为不同二元组的数量,而不是所有二元组的数量(这将提供频率表)。

Map<String, Double> results = new LinkedHashMap<>();
counts.entrySet().stream()
    .sorted(Map.Entry.<String, Long>comparingByValue().reversed()
        .thenComparing(Map.Entry.<String, Long>comparingByKey()))
    .forEachOrdered(e -> results.put(e.getKey(), e.getValue() / denominator));

System.out.println(results);

通过使用 LinkedHashMap 可以保持插入到地图中的顺序。 作为排序顺序,我首先选择最频繁的,然后是二元文本。

我立即将分母设为双精度,以便进行浮点除法,而不是整数除法。

虽然流表示法带有苛刻的语法,但它非常紧凑。

【讨论】:

  • 非常感谢!我花了几天时间阅读了 hashmaps 上的 java 文档。这是一个非常好的解决方案。 @Joop Eggen
【解决方案2】:

这就是你要找的吗?

public static String sortCountBigrams(ArrayList<String> bigrams) {
    String outputResult = "";
    Collections.sort(bigrams);
    int size = bigrams.size(); //use size to get the total no of elements
    String curr = bigrams.get(0);
    int counter = 1;
    for (String next : bigrams) {
        if (next.equals(curr)) {
            counter++;
        } else {
            outputResult += curr + " " + (Double.toString(counter))/size + " "; //divide by size here 
            counter = 1;
            curr = next;
        }
    }
    return outputResult; 
}

【讨论】:

  • 这是正确的,但我的问题是如何找到分母,或者字符串中的二元组数。为简单起见,我在示例中给出了一个常数 8。
  • 使用 size() 查找总元素或将它们添加到 hashset 以便只有唯一的条目,以便您可以计算它们。
  • 我对hashsets的理解是,它是根据数组中的item索引计算的。由于每个双精度数和字符对中有多个字符,因此数组中的字符数不是我想要的。我不熟悉 size() 函数,在 javadocs 中也找不到..
【解决方案3】:

SortedMap 中创建一个Map,其中键是二元组,值是它们对应的频率(在此处使用TreeMap)。

然后计算所有频率的总和。

最后,遍历映射键(bigrams)并计算它们的概率(作为频率/总和)

public static String sortCountBigrams(List<String> inputList) {
    Map<String, Integer> bigramsAndFrequencies = new TreeMap<>();

    // Make the Map and calculate the sum of frequencies
    int sum = 0;
    int frequency;
    String bigram;
    for(int i=0; i<inputList.size(); i = i+2) {
        bigram = inputList.get(i);
        frequency = Integer.valueOf(inputList.get(i+1));
        bigramsAndFrequencies.put(bigram, frequency);
        sum += frequency;
    }

    System.out.println("sum = " + sum);
    System.out.println("bigramsAndFrequencies = " + bigramsAndFrequencies);

    // Build the output String
    StringBuilder sb = new StringBuilder();
    boolean first = true;
    for(String b : bigramsAndFrequencies.keySet()) {
        if(!first) {
            sb.append(" ");
        }
        first = false;
        sb.append(b)
          .append(" ");
          .append((double)bigramsAndFrequencies.get(b) / (double)(sum));
    }

    System.out.println(sb.toString());

    return sb.toString();
}

输出

sum = 720
bigramsAndFrequencies = {af=22, ag=22, ah=7, ai=53, aj=74, ak=1, al=384, am=157}
af 0.030555555555555555 ag 0.030555555555555555 ah 0.009722222222222222 ai 0.07361111111111111 aj 0.10277777777777777 ak 0.001388888888888889 al 0.5333333333333333 am 0.21805555555555556

sb.append(b)
  .append(" ")
  .append(bigramsAndFrequencies.get(b))
  .append("/")
  .append(sum);

如果你想要这种输出格式:

af 22/720 ag 22/720 ah 7/720 ai 53/720 aj 74/720 ak 1/720 al 384/720 am 157/720

【讨论】:

    猜你喜欢
    • 2017-08-05
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-20
    相关资源
    最近更新 更多