【问题标题】:Removing Elements From One List If not contained in another List. C# [duplicate]从一个列表中删除元素如果不包含在另一个列表中。 C# [重复]
【发布时间】: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{
            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;
        }
    }

【问题讨论】:

标签: c# list unity3d


【解决方案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 没有的元素怎么办?
    • 嗯..你是对的。对不起。
    • 而且我需要能够在删除之前停用该块。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    • 2022-01-24
    相关资源
    最近更新 更多