如何使用LINQ在C#中删除列表中的第一个元素出现?

6
我有以下清单。
List<string> listString = new List<string>() { "UserId", "VesselId", "AccountId", "VesselId" };

我想使用一个Linq运算符,它只删除第一次出现的VesselId。

1
可能是Linq skip first where (linq to objects)的重复问题。 - Mark Jansen
看起来不像C#。另外,你真正想要什么?你试图清理重复项吗? - Alex
这不是Linq,但可以完成任务:listString.Remove("VesselId"); - Tim Ashton
LINQ 不会删除任何内容,它只进行查询 - Gert Arnold
你的问题不清楚。删除第一个“VesselId”很简单,那不可能是问题。你是指如何去除重复项吗? - Gert Arnold
5个回答

6

您无法使用 LINQ 更改原始集合,因此最接近的方法是:

var index = listString.IndexOf("VesselId");
if(index>-1)
   listString.RemoveAt(index);

编辑 1:

根据 Igor Mesaros 进行的研究,我最终实现了位于 List.Remove 方法中的逻辑,因此更简单的解决方案是:

listString.Remove("VesselId");

4
如果您有一个简单的字符串列表或其他原始类型,那么您可以直接调用以下方法:
listString.Remove("VesselId");

如@Eyal Perry所提到的

如果您有一个非常庞大的非原始列表,这是最有效的方式

class MyClass
{
   string Name {get; set;}
}

var listString = new List<MyClass>() {/* Fill in with Data */};
var match = listString.FirstOrDefault(x => x.Name == "VesselId");

if(match != null)
     listString.Remove(match);

第一行和第二行代码完全是多余的。 - Eyal Perry
如果类的作者想要使用Remove方法,那么他需要重写Equals方法,因为我敢打赌Remove方法会调用它。此外,请注意,问题的作者对LINQ并不了解,这并不会改变原始集合。他可能想要使用某种简写方式,而不是自己迭代集合。 - Eyal Perry
只有在使用Remove函数的显式实现时,隐式实现不需要Type T类继承IComparable接口。是的...我没有意识到有人在问如何使用.Remove。 - Igor Meszaros
如果您说的是隐式实现中的 Enumerable,我认为隐式实现隐含要求必须实现该接口,除非您调用一个接收比较器实例的重载。单独使用 Remove() 是相当不错的,甚至比我提出的解决方案更好,如果您信任它的文档说明的话。我有点偏执,因为我曾经发现过一些差异,因此我提出了我的解决方案,以确保所需的行为。 - Eyal Perry
1
// 移除给定索引处的元素。列表大小减少一。 // public bool Remove(T item) { int index = IndexOf(item); if (index >= 0) { RemoveAt(index); return true; } return false; }这不关心它是否可比较.. FirstOrDefault将返回需要移除的完全相同的实例,它不需要进行比较! - Igor Meszaros
显示剩余3条评论

1

如果你想获取一个不同的列表,那么你可以使用该列表的扩展方法listString.Distinct()。


列表太长了,这将会花费很多时间。有没有更短的方法? - DenisSuarez
@DenisSuarez - 你的数据从哪里来?你控制它的插入还是从某个地方获取它。如果你把元素放进去,那么你可以从List更改为HashSet,然后首先查看它是否已经存在于集合中。(使用HashSet因为它的时间复杂度是o(1),而不是o(n)) - Gilad Green
1
@GiladGreen Distinct肯定会遍历整个列表,对于指定的用例来说有点过度,因为它的目的是移除第一个遇到的项,这可能只需要遍历部分列表,更不用说无限产生项的IEnumerable了。 - Eyal Perry
@Eyal Perry - 我同意你的观点。这就是为什么我问他信息来源的地方 - 特别是“VesselID”或任何重复的内容。 - Gilad Green
@GiladGreen :) 另外,对于未来的谷歌搜索者来说...Distinct 也会分配一个新的集合,而问题的作者明显希望从现有的集合中删除该项。 - Eyal Perry

0

如果你非常需要使用LINQ,你可以在Remove()方法中使用它来查找第一个"VesselId"实例,像这样:

listString.Remove((from a in listString
                   where a == "VesselId"
                   select a).First());

-1
listString = listString.Union(new List<string>()).ToList();

或者

List<string> CopyString = new List<string>();
            CopyString.AddRange(listString);
            foreach (var item in CopyString)
            {
                var index = CopyString.IndexOf(item);
                if (index >= 0 && listString.Count(cnt => cnt == item) > 1)
                    listString.RemoveAt(index);
            }

这会抛出一个异常,因为你不能从正在迭代的集合中删除项目!此外,即使不抛出异常,这也会完全清除你的集合! - Igor Meszaros
添加 if 语句 listString.Count(cnt=>cnt==item)>1 (System.Linq)。 - Alper Şaldırak
这仍然无法工作,更多信息请参见:https://dev59.com/k3RA5IYBdhLWcg3w_C8w - Igor Meszaros
@IgorMesaros 看看!! - Alper Şaldırak
请参考 @Eyal Perry 的答案。 - Igor Meszaros

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接