Removing alternate elements in a List

后端 未结 8 1091
执笔经年
执笔经年 2021-02-12 18:41

What is the most efficient way to remove alternate (odd indexed or even indexed) elements in an List without using a place holder list variable?

A

相关标签:
8条回答
  • 2021-02-12 18:50
    for (int i=myList.length-1; i >= 0; i--)
      if (i % 2 == 0)
        myList.Remove(myList[i]);
    
    0 讨论(0)
  • 2021-02-12 18:51

    Just for consideration of a solution that creates a new list, with a list old you could do this:

    var newList = old.Where((_, i) => i%2 != 0).ToList();
    

    or, obviously

    var newList = l.Where((_, i) => i%2 == 0).ToList();
    

    depending which alternation you choose.

    EDIT

    The answer is quite a bit quicker. If you read something else here, it's because I measured on a weekend and weekend's brain is funny. :( The closure solution is about 40% quicker while the answer is app. 2 orders of magnitude faster. I suppose it will really depend how big your list becomes!

    0 讨论(0)
  • 2021-02-12 18:51

    And another option, similar to Frank's one, but with usage of closures. And it is quicker than Frank's version.

    bool isEven = true;            
    var newList = list.Where(x => isEven = !isEven).ToList();
    
    0 讨论(0)
  • 2021-02-12 18:52

    Obviously usage dependent, but you could have a wrapper IList that multiplies the index you give it by 2, and reports the length of the list to be 1/2 (details elided). This is O(1).

    0 讨论(0)
  • 2021-02-12 18:53

    I'm not sure what you mean by alternate but if you mean "every other item" the following code will work. It will start by removing the 2nd element, then the 4th, and so on

    List<T> list = GetTheList();
    int i = 1;
    while ( i < list.Count ) {
      list.RemoveAt(i);
      i++;
    }
    
    0 讨论(0)
  • 2021-02-12 18:57

    If you call RemoveAt for every item you remove, you will be moving a lot of data. The most efficient is to move the items together that you want to keep, then remove the unused items at the end:

    int pos = 0;
    for (int i = 0; i < values.Count; i += 2, pos++) {
        values[pos] = values[i];
    }
    values.RemoveRange(pos, values.Count - pos);
    

    Edit:
    This method will process a list of a million ints in 15 ms. Using RemoveAt it will take over three minutes...

    Edit2:
    You could actually start with pos=1 and i=2 (or 3), as the first item doesn't have to be copied to itself. This makes the code a bit less obvious though.

    0 讨论(0)
提交回复
热议问题