0

C#のジェネリックリストの範囲に値を追加する方法を知っている人はいますか?

私は現在、大規模なビルドを行ってList<List<int>>おり、プロセス全体に時間がかかりすぎています。時間を節約するために、foreachループとネストされたforeachループの使用を避けようとしています。

ジェネリックリストに600行あったとしましょう。最初の200行のそれぞれに、「1」を追加したいと思います。次の200では、「2」を追加したいと思います。次の200では、「3」を追加したいと思います。

今のやり方では、600回ループしてそれぞれを個別に追加する必要がありますが、やりたいのは3回ループしてエントリをまとめて追加することです。

私が望んでいたコードは次のようになります。

List<List<int>> idList = GetFullList(); //list contains 600 rows

int[] newItems = {1, 3, 5};
int count = 0;
int amountToAmend = 200;
foreach (int i in newItems)
{
    //List<int> newID = new List<int>();
    //newID.Add(i);
    (idList.GetRange(count, amountToAmend)).Add(i);    
    count += amountToAmend;
}

明らかにこれは機能しませんが、うまくいけば、私が目指しているようなものを見ることができます。私のアプリケーションでは、現在、何万もの不要なループを実行する必要があります。コードが存在する場合、10未満で実行できることがよくあります。

更新:私はこれをうまく説明したかどうかわからないので、明確にするために、ここに私が探している結果があります

このように6行のリストがある場合:

[6,7,8]
[5,6,7]
[6,4,8]
[2,4,7]
[5,1,7]
[9,3,5]

最初の3行に1を追加し、次の3行に2を追加したいので、次のようになります。

[6,7,8,1]
[5,6,7,1]
[6,4,8,1]
[2,4,7,2]
[5,1,7,2]
[9,3,5,2]

これはforeachループで簡単に実行でき、現在の方法ですが、膨大な量のデータが関係しているため、特定の機能にかかる時間を短縮する方法を探しています。方法が存在するかどうかはわかりませんが、誰かが知っているなら、それはStackOverflowの良い人になるでしょう:)

4

5 に答える 5

0
List<List<int>> idList = GetFullList(); //list contains 600 rows  

var iterator = idList.Begin();

int[] newItems = {1, 3, 5};  
int count = 0;  
int amountToAmend = 200;  
foreach (var item in newItems)
{
   iterator = iterator.AddItem(item);
   iterator = iterator.MoveForward(amountToAmend);
}

public struct NestedListIterator<T>
{
  public NestedListIterator(List<List<T>> lists, int listIndex, int itemIndex)
  {
    this.lists = lists;
    this.ListIndex = listIndex;
    this.ItemIndex = itemIndex;
  }
  public readonly int ListIndex;
  public readonly int ItemIndex;
  public readonly List<List<T>> lists;

  public NestedListIterator<T> AddItem(T item)
  {
    var list = lists.ElementAtOrDefault(ListIndex);
    if (list == null || list.Count < ItemIndex)
      return this;//or throw new Exception(...)
    list.Insert(ItemIndex, item);
    return new NestedListIterator<T>(this.lists, this.ListIndex, this.ItemIndex + 1);
  }
  public NestedListIterator<T> MoveForward(List<List<T>> lists, int index)
  {
    //if (index < 0) throw new Exception(..)
    var listIndex = this.ListIndex;
    var itemIndex = this.ItemIndex + index;
    for (; ; )
    {
      var list = lists.ElementAtOrDefault(ListIndex);
      if (list == null)
        return new NestedListIterator<T>(lists, listIndex, itemIndex);//or throw new Exception(...)
      if (itemIndex <= list.Count)
        return new NestedListIterator<T>(lists, listIndex, itemIndex);

      itemIndex -= list.Count;
      listIndex++;
    }
  }
  public static int Compare(NestedListIterator<T> left, NestedListIterator<T> right)
  {
    var cmp = left.ListIndex.CompareTo(right.ListIndex);
    if (cmp != 0)
      return cmp;
    return left.ItemIndex.CompareTo(right.ItemIndex);
  }
  public static bool operator <(NestedListIterator<T> left, NestedListIterator<T> right)
  {
    return Compare(left, right) < 0;
  }
  public static bool operator >(NestedListIterator<T> left, NestedListIterator<T> right)
  {
    return Compare(left, right) > 0;
  }
}
public static class NestedListIteratorExtension
{
  public static NestedListIterator<T> Begin<T>(this List<List<T>> lists)
  {
    return new NestedListIterator<T>(lists, 0, 0);
  }
  public static NestedListIterator<T> End<T>(this List<List<T>> lists)
  {
    return new NestedListIterator<T>(lists, lists.Count, 0);
  }
}
于 2012-07-25T10:21:56.747 に答える
0

LINQSkipの およびメソッドを使用できます。Take

リストから最初の 200 個のアイテムが表示されるようidList.Skip(0).Take(200)に、これらのアイテムを更新できます。

更新の場合、次のように言うことができます。

int increment=2;
list.Select(intVal=> intVal+increment).ToList();
于 2012-07-25T09:45:14.170 に答える
0

amountToAmendの各アイテムを回したいnewItemsですか?
Like :
200回 1
200回 3
200回 5

もしそうなら、あなたは試すことができます:

int amountToAmend = 200;
List<int> newItems = new List<int>(){ 1, 3, 5 };
<List<int>> idList = new List<List<int>>();
newItems.ForEach(i => idList.Add(new List<int>(Enumerable.Repeat(i, amountToAmend))));
于 2012-07-25T10:02:18.170 に答える
0

すべてのリストに新しい要素を追加する必要があるため、ループ (明示的または暗黙的) をまったく回避することはできませんが、組み込み関数はありません。

List.GetRangeと組み合わせることができますList.ForEach

var newItems = new[] { 1, 2 };
int numPerGroup = (int)(idList.Count / newItems.Length);
for (int i = 0; i < newItems.Length; i++)
    idList.GetRange(i * numPerGroup, numPerGroup)
          .ForEach(l => l.Add(newItems[i]));

上記はLinqではなく、.NET 2.0でも機能することに注意してください


これはあなたが必要としていたものではなかった私の古いアプローチです:

とを使用LinqEnumerable.GroupByて、フラット リストをネストされたリストに再配布できます。

int amountToAmend = 200;
// create sample data with 600 integers
List<int> flattened = Enumerable.Range(1, 600).ToList();  
// group these 600 numbers into 3 nested lists with each 200 integers
List<List<int>> unflattened = flattened
    .Select((i, index) => new { i, index })
    .GroupBy(x => x.index / amountToAmend)
    .Select(g => g.Select(x => x.i).ToList())
    .ToList();

デモはこちら: http://ideone.com/LlEe2

于 2012-07-25T09:50:28.447 に答える
0

これはどう:

foreach (int i in newItems)
{
    foreach (var row in idList.Skip(count).Take(amountToAmend)) 
    {
        row.Add(i);
    }
    count += amountToAmend;
}

または for ループを使用:

foreach (int i in newItems)
{
    for (int j = 0; j < amountToAmend; j++)
    {
        idList[count + j].Add(i);
    }
    count += amountToAmend;
}
于 2012-07-25T09:47:50.800 に答える