代码之家  ›  专栏  ›  技术社区  ›  abhilash

删除列表中的备用元素<T>

  •  18
  • abhilash  · 技术社区  · 16 年前

    在一个数据库中删除备用(奇数索引或偶数索引)元素的最有效方法是什么 List<T>

    我在找一份工作 有效率的 如何做到这一点

    提前谢谢

    8 回复  |  直到 16 年前
        1
  •  28
  •   Guffa    16 年前

    如果您为删除的每个项目调用RemoveAt,您将移动大量数据。最有效的方法是将要保留的项目移动到一起,然后在最后删除未使用的项目:

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

    编辑:
    此方法将在15毫秒内处理一百万个整数的列表。使用RemoveAt将花费三分钟以上。。。


    实际上,您可以从pos=1和i=2(或3)开始,因为第一项不必复制到自身。这使得代码不那么明显。

        2
  •  9
  •   Derek Beattie    8 年前

    只是为了考虑创建一个新列表的解决方案 古老的

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

    或者,很明显

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

    编辑

    答案要快一点。如果你在这里读到其他东西,那是因为我在周末测量,周末的大脑很有趣( 关闭解决方案比应用程序快40%左右。快2个数量级。我想这将真正取决于你的名单有多大!

        3
  •  5
  •   Martin JonáÅ¡    16 年前

    还有另一个选项,与Frank的类似,但使用闭包。而且比弗兰克的版本快。

    bool isEven = true;            
    var newList = list.Where(x => isEven = !isEven).ToList();
    
        4
  •  2
  •   JaredPar    16 年前

    我不确定你所说的替代品是什么意思,但如果你是说“其他每一项”,那么下面的代码就可以了。首先移除第二个元素,然后移除第四个元素,依此类推

    List<T> list = GetTheList();
    int i = 1;
    while ( i < list.Count ) {
      list.RemoveAt(i);
      i++;
    }
    
        5
  •  2
  •   Jay Bazuzi Buck Hodges    16 年前

        public static IEnumerable<T> AlternateItems<T>(this IEnumerable<T> source)
        {
            while (source.Any())
            {
                yield return source.First();
    
                source = source.Skip(1);
    
                if (source.Any()) source = source.Skip(1);                
            }
        }
    

    这适用于所有序列,而不仅仅是 IList<> . 迭代的成本被推迟到迭代,如果最终不需要触及列表中的所有元素,这可能是一个巨大的胜利。

    在我的简单测试中,迭代整个列表时的性能不是很好,因此请务必分析您的实际情况。

        6
  •  1
  •   tsilb    16 年前
    for (int i=myList.length-1; i >= 0; i--)
      if (i % 2 == 0)
        myList.Remove(myList[i]);
    
        7
  •  1
  •   wowest    16 年前

    显然,这取决于使用情况,但是您可以使用一个包装器IList,将您提供的索引乘以2,并报告列表的长度为1/2(细节省略)。这是O(1)。

        8
  •  0
  •   Loki Astari    16 年前

    执行删除操作,然后执行擦除操作。

    这样,您就不会混淆习惯于看到这种模式的人。

    template<typename T>
    struct RemoveEven
    {
        RemoveEven():count(0)   {}
        bool operator()(T const&)
        {
            bool    result  =  count%2 == 0;
            count++;
            return result;
        }
        private:
            std::size_t count;
    };
    int main()
    {
        std::list<int>  a;
        a.erase(std::remove_if(a.begin(),a.end(),RemoveEven<int>()),a.end());
    
    }