.net 如何从对象列表中删除(通过linq)重复项

vmpqdwk3  于 2023-03-04  发布在  .NET
关注(0)|答案(5)|浏览(159)

我的主对象,有一个属性,这是一个标签列表

[SharedCosmosCollection("shared")]
    public class GlobalPageTemplate : ISharedCosmosEntity
    {
        /// <summary>
        /// Id
        /// </summary>
        [JsonProperty("Id")]
        public string Id { get; set; }

        /// <summary>
        /// Cosmos Entity name
        /// </summary>
        [CosmosPartitionKey]
        public string CosmosEntityName { get; set; }

        /// <summary>
        /// Page name
        /// </summary>
        public string ExtractedPageName { get; set; }

        /// <summary>
        /// Site collection Template Name
        /// </summary>
        public string ExtractedSitecollectionTemplateName { get; set; }

        /// <summary>
        /// GlobalDesignTenantId
        /// </summary>
        public string ExtractedGlobalDesignTenantId { get; set; }

        /// <summary>
        /// Global design tenant site collection url
        /// </summary>
        public string ExtractedGlobalDesigntenantSiteCollectionUrl { get; set; }

        /// <summary>
        /// Page template picture Url
        /// </summary>
        public string PageTemplatePictureUrl { get; set; }

        /// <summary>
        /// Base64 image of the page template
        /// </summary>
        public string Base64Image { get; set; }

        /// <summary>
        /// Name of the template
        /// </summary>
        public string PageTemplateName { get; set; }

        /// <summary>
        /// Page sections
        /// </summary>
        public List<Section> Sections { get; set; }

        /// <summary>
        /// Tags
        /// </summary>
        public List<Tag> Tags { get; set; }
    }

标记对象位于此处:

public class Tag : ISharedCosmosEntity
    {
        /// <summary>
        /// Id
        /// </summary>
        [JsonProperty("Id")]
        public string Id { get; set; }
        /// <summary>
        /// Tag name
        /// </summary>
        public string TagName { get; set; }
        /// <summary>
        /// cosmos entity name
        /// </summary>
        [CosmosPartitionKey]
        public string CosmosEntityName { get; set; }
    }

在我的WebAPI中,从前端,我可能会得到重复的标记,
如何在保存之前删除它们并留下一个干净的标签列表?

hjzp0vay

hjzp0vay1#

我可以建议您将存储标签的数据结构更改为HashSet吗?如果可以,您可以执行类似this的操作。
HashSet是唯一元素的无序集合。它通常用于防止重复元素被放置在集合中。与列表相比,HashSet的性能要好得多。
实际上,您在初始化时为HashSet提供了一个自定义的IEqualityComparer。

public class TagComparer : IEqualityComparer<Tag>
{
    public bool Equals(Tag x, Tag y)
    {
        return x.Id.Equals(y.Id, StringComparison.InvariantCultureIgnoreCase);
    }

    public int GetHashCode(Tag obj)
    {
        return obj.Id.GetHashCode();
    }
}

然后你就可以

HashSet<Tag> Tags = new HashSet<Tag>(new TagComparer());

一般来说,我总是尝试使用对手头的问题有意义的数据结构,如果你知道你总是希望这个集合有唯一的元素,那么我建议你使用HashSet。
如果不能使用HashSet,而又想使用列表,可以在Tags列表上使用linq的Distinct方法,并从上面传入TagComparer对象。

List<Tag> DistinctTagList = Tags.Distict(new TagComparer())
rjee0c15

rjee0c152#

不完全是你的问题的答案(其他答案都是有效的解决方案),但是如果出于某种原因,你希望实际提取你的重复对象,比如为了调试、错误处理等等,我想提供下面的答案。

var duplicates = someList
  .GroupBy(r => r.Id)
  .Where(g => g.Count() > 1)
  .ToList();

然后,您可以使用一种稍微不同的方法来管理您的列表

someList = someList.Except(duplicates).ToList();

它是一个没有重复项的密钥列表。

avwztpqn

avwztpqn3#

你要找的可能是distict方法:https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.distinct?view=netframework-4.8
为此,您还需要编写一个IEqualityComparer,它可以简单地通过属性https://learn.microsoft.com/en-us/dotnet/api/system.collections.generic.iequalitycomparer-1?view=netframework-4.8进行比较
然后,您可以在Enumerable上调用它:

var distinctTags = Tags.Distict(new TagEqualityComparer)

以及相等比较器:

class TagEqualityComparer : IEqualityComparer<Tag>
{
    public bool Equals(Tag t1, Tag t2)
    {
        if (t2 == null && t1 == null)
           return true;
        else if (t1 == null || t2 == null)
           return false;
        else if(t1.Id == t2.Id)
            return true;
        else
            return false;
    }

    public int GetHashCode(Tag t)
    {
        // any custom hashingfunction here
    }
}
pqwbnv8z

pqwbnv8z4#

使用 only linq您可以做到这一点:
如果标记具有唯一ID:

tags.GroupBy(x => x.Id).Select(x => x.First()).ToList();

如果需要比较所有列:

tags.GroupBy(x => new {x.Id, x.TagName, x.CosmosEntityName}).Select(x => x.First()).ToList();
b4qexyjb

b4qexyjb5#

var applications = from i in db.Users
                               join m in db.Messages on i.Id equals m.fromId
                               where m.toId == userID
                               orderby m.messageId descending
                               select i;

            Cusers = applications.DistinctBy(x => x.Id).ToList();

相关问题