使用 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);
如果我理解正确的话,如果某些十进制/双精度值“足够接近”,您希望有某种方法将对象放入“桶”中。为此,我可以建议非常直接的实施:
检查所有有问题的十进制值,首先使用第一个项目创建第一个存储桶,然后对于每个下一个项目检查是否存在匹配的存储桶(基于它们之间的最大差异),如果不存在这样的存储桶,则创建新的存储桶。
以下是示例扩展方法的实现:
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());
}
}