我正在使用Microsoft Translator API,特别是TranslateArray方法。我的挑战是texts
参数的内置限制:
[...]包含翻译文本的数组。 [...]所有要翻译的文本总数不得超过10000个字符。数组元素的最大数量为2000。
我得到一个可变长度的List元素 - 每个元素都有不同的长度(标题,描述)。我想将此数据传递给TranslateArray()
,但它需要具有适当的大小。我怎么能这样做?
public class TranslateItem
{
public string Title { get; set; }
public string Desc { get; set; }
}
private static void chunkNorris()
{
// list contains elements to be translated
var list = new List<TranslateItem>();
var chunkList = new List<TranslateItem>();
int itemLength = 0; int totalLength = 0;
foreach (var batch in list.Batch(1000))
{
foreach (var item in batch)
{
itemLength = item.Title.Length + item.Desc.Length;
totalLength = totalLength + itemLength;
if (itemLength <= 10000 && totalLength <= 10000)
{
chunkList.Add(new TranslateItem() { Title = item.Title, Desc = item.Desc });
}
else
{
// do translation here...
// bug here: itemLength can be > 10000
// reset chunkList and add item to empty list
chunkList.Clear();
itemLength = totalLength = item.Title.Length + item.Desc.Length;
chunkList.Add(new TranslateItem() { Title = item.Title, Desc = item.Desc});
}
if (item.Equals(list.Last()))
{
// do translation here...
}
}
}
}
更新:这就是我所拥有的。代码将以1000“批次”(即2列的1000个元素)运行并拆分数组,以符合2000数组元素限制。但是,它不能解决大小超过10,000个字符的问题。此外,代码非常笨拙 - 想知道是否可以使用LINQ以更优雅的方式完成。 Batch method from here
答案 0 :(得分:1)
实际上,您应该修改Batch
方法以获得两个分块规则而不是一个。也就是说,让我们从头开始吧。这里的基本技巧是利用C#内置的IEnumerable/yield
支持。
您的目标是批量翻译项目。
public class TranslateItem
{
public string Title { get; set; }
public string Desc { get; set; }
}
所以,让我们从签名开始吧。给定一些要翻译的项目(IEnumerable<TranslateItem>
),返回一些要翻译的分块项目(IEnumerable<IEnumerable<TranslateItem>>
)
private static IEnumerable<IEnumerable<TranslateItem>>
chunkNorris(IEnumerable<TranslateItem> data)
{
保持正在运行的一批项目进行翻译,跟踪该批次中字符的总长度:
var chunkList = new List<TranslateItem>();
int totalLength = 0;
逐个处理每个项目
foreach (var item in data)
{
计算批次中当前项目的长度:
int itemLength = item.Title.Length + item.Desc.Length;
如果该项目有10000个字符,请以某种方式处理:
if (itemLength > 10000)
{
throw new NotImplementedException("TODO");
}
将该项目添加到当前批次是安全的,如果这样做不会违反我们的两条规则(不超过1000项/ 2000字符串且不超过10000个字符)。
bool SafeToAddMoreData =
(itemLength+totalLength) <= 10000 && chunkList.Count < 1000;
如果扩展我们当前的块是不安全的,只需产生当前块,然后再创建一个新块。
if(!SafeToAddMoreData)
{
yield return chunkList;
chunkList = new List<TranslateItem>();
totalLength = 0;
}
现在可以安全地向我们当前的块添加更多数据,因为SafeToAddMoreData
是假的,或者因为我们刚刚清除了当前的块。因此,向我们当前的块添加更多数据,确保更新块长度的运行总计。
totalLength = totalLength + itemLength;
chunkList.Add(item);
对每个块重复此过程
}
我们的循环只在数据被阻止扩展当前块时才会吐出数据。吐掉最后一块。
if (chunkList.Any()) //Always be true (unless data was empty).
{
yield return chunkList;
}
该功能已完成。
}