Tengo la siguiente lista de etiquetas:

List<Tag> tags = new List<Tag> {
  new Tag { Name = "Book", Slug = "book" },
  new Tag { Name = "Travel", Slug = "travel" } 
}

Y tengo una lista de publicaciones donde cada publicación tiene algunas etiquetas:

List<Post> model = new List<Post> {
  new Post {
    Title = "First Post",
    Tags = new List<Tag> { 
      new Tag { Name = "Book", Slug = "book" },
      new Tag { Name = "Europe", Slug = "europe" } 
    },
  },
  new Post {
    Title = "Second Post",
    Tags = new List<Tag> { 
      new Tag { Name = "Travel", Slug = "travel" },
      new Tag { Name = "Europe", Slug = "europe" } 
    }
  }
};

Para cada publicación, necesito redefinir las etiquetas, basándome en slug, con las instancias en las etiquetas.

La primera publicación tiene dos etiquetas con las siguientes babosas book y europe.

Necesito obtener de tags el primero porque tiene la babosa book existente en las Etiquetas de la publicación.

Entonces la propiedad Publicar etiquetas será:

List<Tag> tags = new List<Tag> {
  tags[0]
}

Entonces necesito usar la instancia en las etiquetas.

¿Cómo puedo hacer esto?

0
Miguel Moura 18 abr. 2020 a las 18:19

2 respuestas

La mejor respuesta

Si desea eliminar las etiquetas que no están en la lista tags (basadas en la propiedad Slug) y reemplazar las instancias Tag por las declaradas en la variable tags, puede hacer esto:

foreach (var post in model)
{
    post.Tags = tags.Where(t => post.Tags.Any(u => u.Slug == t.Slug)).ToList();
}

Esto no crea nuevas instancias Post como en la respuesta @Sajid.

3
Nicolas Mandica 18 abr. 2020 a las 15:55

Otra solución podría ser crear una clase IEqualityComparer<Tag>:

public class TagEqualityComparer : IEqualityComparer<Tag>
{
    public bool Equals(Tag x, Tag y)
    {
        return x.Slug == y.Slug;
    }

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

Luego pase este comparador a { {X0}} de LINQ para encontrar etiquetas que se crucen:

var result = model
    .Select(post => new Post
    {
        Title = post.Title,
        Tags = post.Tags.Intersect(tags, new TagEqualityComparer()).ToList()
    })
    .ToList();

Podría ser excesivo para su escenario, pero como mencionó intersección no pensé que sería una mala idea publicar esto.

Si la clase Tag se hace más grande con más propiedades, entonces la solución anterior también podría ser beneficiosa, ya que puede actualizar los métodos Equals y GetHashCode y pasar el comparador en su lugar.

También puede reutilizar el mismo comparador para otros métodos LINQ como Except, OrderBy, SequenceEqual etc., que también podrían ser beneficiosos.

0
RoadRunner 18 abr. 2020 a las 16:19