如果 Y 位置差异较小,如何将文本分组到行

问题描述 投票:0回答:1

使用 PdfPig 从订单 PDF 中读取文本,如使用 C# 从 PDF 中逐行获取文本答案

中所述
  static void GetWordsInReadingOrder(UglyToad.PdfPig.Content.Page page, StringBuilder builder)
  { 
    var words = page.GetWords().ToList();
    var wordsList = page.GetWords().GroupBy(x => x.BoundingBox.Bottom);
    foreach (var word in wordsList)
    {
      bool esimene = true;
      foreach (var item in word)
      {
        if (!esimene)
          builder.Append(' ');
        esimene = false;
        builder.Append($"{item.Text}");
      }
      builder.AppendLine();
    }
  }

如果 x.BoundingBox.Bottom 存在微小差异,则将单个 PDF 行拆分为多行。 如何添加一些容差,以便如果 Y 位置存在微小差异,项目会出现在同一行? 可能应该添加四舍五入到

var wordsList = page.GetWords().GroupBy(x => x.BoundingBox.Bottom);
c# linq pdfbox pdfbox-layout pdfpig
1个回答
0
投票

如果我理解正确的话,如果某些十进制/双精度值“足够接近”,您希望有某种方法将对象放入“桶”中。为此,我可以建议非常直接的实施:

检查所有有问题的十进制值,首先使用第一个项目创建第一个存储桶,然后对于每个下一个项目检查是否存在匹配的存储桶(基于它们之间的最大差异),如果不存在这样的存储桶,则创建新的存储桶。

以下是示例扩展方法的实现:

public static class Bucketing
{
    public static IEnumerable<IGrouping<double, T>> BucketGroupBy<T>(
        this IEnumerable<T> collection,
        Func<T, double> selector,
        double bucketRange)
    {
        var buckets = GetBuckets(
            collection.Select(selector).ToArray(),
            (x, y) => Math.Abs(x - y) < bucketRange);

        var newSelector = (T x) =>
        {
            var decimalValue = selector(x);
            var bucket = buckets.First(i => i.Value.Contains(decimalValue));
            return bucket.Key;
        };

        return collection.GroupBy(newSelector);
    }

    public static Dictionary<double, double[]> GetBuckets(
        double[] numbers,
        Func<double, double, bool> bucketPredicate)
    {
        var buckets = new Dictionary<double, List<double>>();
        var numberList = numbers.ToList();
        foreach (var number in numbers)
        {
            // Already processed
            if (!numberList.Contains(number)) continue;

            var existingBucket = buckets.FirstOrDefault(x => bucketPredicate(x.Key, number));

            if(existingBucket.Value is not null)
            {
                existingBucket.Value.Add(number);
                numberList.Remove(number);
                continue;
            }

            buckets.Add(number, new List<double> { number });
        }

        return buckets.ToDictionary(x => x.Key, x => x.Value.ToArray());
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.