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

时间:2019-10-11 01:13:39

标签: c# list unity3d

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{
            get{return 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;
        }
    }

3 个答案:

答案 0 :(得分:0)

这是一种方法。

对于Active中找不到的activeChunks中的块,以下代码会将chunks更改为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);

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

答案 1 :(得分:0)

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中的项目减去要删除的项目(例如ActiveChunk中的项目,而不是大块中的项目)。
不必从ActiveChunks中删除项目,只需将ActiveChunks替换为activeMinusMissing

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();

答案 2 :(得分:-1)

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