从一个列表中删除元素如果不包含在另一个列表中。 C# [重复]

Posted

技术标签:

【中文标题】从一个列表中删除元素如果不包含在另一个列表中。 C# [重复]【英文标题】:Removing Elements From One List If not contained in another List. C# [duplicate] 【发布时间】:2019-10-11 01:13:39 【问题描述】:

我从List<> A 中删除不在List<> B 中的元素的最佳方法是什么。最重要的是,在我删除 Element 之前,我需要在 Element 上运行一个函数(当值更改时运行回调)。

举例

List<Chunk> ActiveChunks = //List Of Active Chunks.
void UpdateChunks()

   List<Chunk> chunks = //Chunks To Activate
   if (ActiveChunks[Element] is not Contained In chunks)
      A.Active = False
      A.Remove[Element]
   
   //After Removing Chunks That do not exist in "chunks" add from chunks to ActiveChunks What is not In already in Chunks
 

我的代码是什么样子的

private List<Chunk> ActiveChunks = new List<Chunk>();
private void OnPlayerMoved(Character c)

    //Current chunk That Player is in
    List<Chunk> chunks = new List<Chunk>();
    for (int i = -(GameManager.ViewRange - 1); i < GameManager.ViewRange - 1; i++)
    
        Chunk chunk = world.ChunkAtWorldPos(c.PosX + i, c.PosY + i);
        if (chunk != null)
            chunks.Add(chunk);
    
    if (ActiveChunks.Count > 0)
    
        foreach (Chunk chunk in ActiveChunks)
        
            if (chunks.Contains(chunk) == false)
            
                chunk.Active = false;
            
        
        //This Line From Answer down Below
        ActiveChunks.RemoveAll(x => x.Active == false);
        foreach (Chunk chunk in chunks)
        
            if (ActiveChunks.Contains(chunk) == false)
            
                chunk.Active = true;
                ActiveChunks.Add(chunk);
            
        
    
    else
        ActiveChunks.AddRange(chunks);


public class Chunk
    
        //Position
        public readonly int X;
        public readonly int Y;

        public Tile[,] Tiles;

        private bool active = false;
        public bool Active
            getreturn active;
            set
                if (value == true && value != active)
                    cbOnActivate?.Invoke(this);
                else if (value != active)
                    cbOnDeactivate?.Invoke(this);

                active = value;
            
        

        Action<Chunk> cbOnActivate;
        Action<Chunk> cbOnDeactivate;

        //Constructor
        public Chunk(int X, int Y)
        
            this.X = X;
            this.Y = Y;
        

        void RegisterOnActivateCallback(Action<Chunk> callback)
            cbOnActivate += callback;
        
        void RegisterOnDeactivateCallback(Action<Chunk> callback)
            cbOnActivate += callback;
        
    

【问题讨论】:

请参阅 LINQ / IEnumerable“包含”或“任何”作为开始。 你会想要 Linq,但更喜欢 Intersect 形式为 ListA = ListA.Intersect(ListB) 请参阅 docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… 【参考方案1】:

这是一种方法。

对于activeChunks 中在chunks 中找不到的块,以下代码会将Active 更改为false。

我假设:

两个列表中的块都有一个Id 属性 activeChunksActive==false 中没有您想要保留的块。
var chunksInActiveChunksThatDontExistInChunks = 
    activechunks.Where( ch => !chunks.Any( ch => ch.Id == chunk.Id ));

// Since it seems you're not familiar with Linq
// please be aware that this will not be evaluated until foreach is executed
// You can evaluate it earlier by calling ToList() 
// e.g. var chunksIn... = activechunks.Where(...).ToList();


foreach( var chunk in chunksInActiveChunksThatDontExistInChunks )

    chunk.Active = false;


activeChunks.RemoveAll(x => x.Active == false);

如果您的对象匹配,您可以使用Contains,但我不知道他们是否这样做,所以我选择了.Id。可能是:

var chunksInActiveChunksThatDontExistInChunks = 
    activechunks.Where( ch => !chunks.Contains(ch));

对于

//删除“块”中不存在的块后,将块中不存在的块添加到ActiveChunks中

你可以:

var chunksThatAreInChunksButNotInActiveChunks = 
    chunks.Where( ch => !activeChunks.Any( ch => ch.Id == chunk.Id ));

activeChunks.AddRange(chunksThatAreInChunksButNotInActiveChunks);

请注意,如果列表在执行过程中被其他人修改,这不好

【讨论】:

“ch”代表什么? + 块没有“Id” 在此上下文中,ch 代表 activechunks 中当前正在 Linq 操作中处理的元素 (Where)。 activechunks.Except(chunks) 能否包含 Chunk 的声明?如果理解如何比较它们可能很重要,正如@tymtam 在这里指出的那样,他必须假设如何比较两个块。【参考方案2】:
var missing = ActiveChunks.Where(i => !chunks.Contains(i));
missing.ToList().ForEach(i => Console.WriteLine(i));
var activeMinusMissing = ActiveChunks.Where(i => missing.Contains(i));
ActiveChunks = activeMinusMissing;

missing 是一个列表,其中包含 ActiveChunks 中但在 chunks 中缺失的项目(例如,您要删除的项目)

Console.WriteLine() 可以是您喜欢的任何函数,它在要删除的每个项目上运行

activeMinusMissing 是一个列表,其中包含来自 ActiveChunks 的项目减去要删除的项目(例如 ActiveChunks 中但不在块中的项目)。 您可以将ActiveChunks 替换为activeMinusMissing,而不是从ActiveChunks 中删除项目。

activeMinusMissing 变量仅用于演示,因此您可以将最后两行替换为

ActiveChunks= ActiveChunks.Where(i => missing.Contains(i)).ToList();

所以最终的代码是

var missing = ActiveChunks.Where(i => !chunks.Contains(i));
missing.ToList().ForEach(i => Console.WriteLine(i));
ActiveChunks= ActiveChunks.Where(i => missing.Contains(i)).ToList();

【讨论】:

【参考方案3】:

根据您的代码,我认为,activechunks 最终是相同的块。无需添加和删除元素。移除所有 activechunks 元素并将所有 chunks 的元素添加到 activechunks 中。

【讨论】:

如果activeChunks 包含chunks 没有的元素怎么办? 嗯..你是对的。对不起。 而且我需要能够在删除之前停用该块。

以上是关于从一个列表中删除元素如果不包含在另一个列表中。 C# [重复]的主要内容,如果未能解决你的问题,请参考以下文章

EF CORE PostgreSQL - 检查列表的所有元素是不是包含在另一个列表中

python 判断某个列表中的所有元素在另一个列表中

在 Python 中,如何从列表中删除包含某些类型字符的任何元素?

如何在c ++中删除嵌套列表中的重复元素

C语言 删除所有相同值的元素

一道Python练习题引发的,一个知识点的探讨:删除列表中特定元素的几种方法