2017-05-06 17 views
-1

私はMicrosoft Translator API、具体的にはTranslateArrayメソッドを使用しています。私の挑戦は、textsパラメータの組み込み制限です。リストをチャンクする方法<T>?

[...]変換するテキストを含む配列です。 [...]翻訳されるすべてのテキストの合計は10000文字を超えてはいけません。配列要素の最大数は2000です。

さまざまな長さ(Title、Desc)の可変長の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... 
       } 
      } 
     } 
    } 

更新:これは私が持っているものです。コードは、2000個の配列要素の制限に準拠するように、1000個の「バッチ」(つまり、1000個の2列)で配列を実行し分割します。ただし、10,000文字を超えるサイズの問題は修正されません。さらに、コードはかなり不器用です - LINQをより洗練された方法で使用できるかどうか疑問に思っていました。 Batch method from here

+1

簡単な問題を解決します。あなたのリストに1つの要素があったらどうなりますか? –

+0

何を試しましたか?あなたの質問は、述べたように広すぎます。あなたは基本的にスタックオーバーフローがあなたのためにあなたの仕事をするように要求しています。正解には、さまざまな形があります。何か努力をしてから、あなたの質問に良い[mcve]を含めて、そしてあなたが何が問題になっているのかを具体的に説明することを含め、その努力が何だったのかを説明してください。また、問題が不完全に指定されていることにも注意してください。特に、リストのいずれかの要素が10K文字制限を超えている可能性はありますか?もしそうなら、あなたはそれにどのように対処したいのですか?もしそうでなければ、どうしてそんなことが分かりますか? –

+0

例が更新されました。 10,000文字以上の単一要素の問題はまだ修正されません。コードはかなり不器用で、長い昼/夜です。 – Sha

答えて

1

実際には、Batchメソッドを変更して、2つのチャンクルールを1つではなく変更する必要があります。つまり、最初から始めましょう。ここでの基本的なテクニックは、IEnumerable/yieldのためのC#の組み込みサポートを活用することです。

あなたの目標は、翻訳のためのバッチアイテムです。

public class TranslateItem 
{ 
    public string Title { get; set; } 
    public string Desc { get; set; } 
} 

だから、署名から始めましょう。

private static IEnumerable<IEnumerable<TranslateItem>> 
    chunkNorris(IEnumerable<TranslateItem> data) 
{ 

、翻訳し、いくつかは(IEnumerable<IEnumerable<TranslateItem>>)変換するためのアイテムをチャンク返すためにいくつかの項目(IEnumerable<TranslateItem>)を考えるとそのバッチ内の文字の長さの合計を追跡し、翻訳した項目の実行中のバッチを保持:

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"); 
     } 

そうすることが私たちの2つのルールを違反しない場合は、当社の現在のバッチにその項目を追加するために安全である(なし1000以上のアイテム/ 2000文字列、10000文字以下)。

 bool SafeToAddMoreData = 
      (itemLength+totalLength) <= 10000 && chunkList.Count < 1000; 

現在のチャンクを展開するのが安全でない場合は、現在のチャンクを作成してから新しいチャンクを作成してください。

 if(!SafeToAddMoreData) 
     { 
      yield return chunkList; 
      chunkList = new List<TranslateItem>(); 
      totalLength = 0; 
     } 

私たちの現在のチャンクにデータを追加しても安全である、のいずれかSafeToAddMoreDataはfalseであるためか、私達はちょうど私たちの現在のチャンクをクリアしているため。したがって、現在のチャンクにデータを追加してください。チャンク文字の長さのランニング・トータルを必ず更新してください。それは現在のチャンクを拡大してからブロックされたとき、すべてのチャンク

} 

当社のforループ

 totalLength = totalLength + itemLength; 
     chunkList.Add(item); 

を繰り返し、このプロセスは、データだけを出してくれる。最後のチャンクを吐き出す

if (chunkList.Any()) //Always be true (unless data was empty). 
    { 
     yield return chunkList; 
    } 

機能が行われます。

} 
関連する問題