Samantha J T Star
Samantha J T Star

Reputation: 32808

How can I add and remove records from a collection with LINQ

I have the following class called City that contains another class called Detail.

 public class City
    {
        public override string PartitionKey { get; set; }
        public override string RowKey { get; set; }
        public string Title { get; set; }

        public class Detail {
            public Detail() {
                Text = new HtmlText();
            }
            public HtmlText Text { get; set; }
        }

}

public class HtmlText {

public HtmlText()
{
    TextWithHtml = String.Empty;
}
[AllowHtml]
public string TextWithHtml { get; set; } 

}

In my code I use the following to create a list of details. Later on I populate some of the details but not all.

IList<City.Detail> Details = Enumerable.Range(1,6).Select(x => new City.Detail()).ToList();

I need to be able to do two things. Can someone tell me the best way to do this. Hopefully using LINQ.

Upvotes: 1

Views: 438

Answers (3)

Shahar G.
Shahar G.

Reputation: 1510

a)

Details = 
   Details
   .Except(Details
       .Where(d => string.IsNullOrEmpty(d.Text.TextWithHtml)))
   .ToList();

b)

 Details = 
    Details
      .Concat(
        Enumerable
        .Range(1, 6 - Details.Count())
        .Select(x => new City.Detail()))
      .ToList();

Upvotes: 0

Tim S.
Tim S.

Reputation: 56536

@YavgenyP answered your first question well. For the second question, here's what I'd recommend:

while (Details.Count < 6)
    Details.Add(new City.Detail());

Trying to do this with LINQ is just all-around worse (length, readability, speed):

if (Details.Count < 6)
    Enumerable.Range(1, 6 - Details.Count).Select(x =>
    {
        var d = new City.Detail();
        Details.Add(d);
        return d;
    }).ToArray();

While I like his solution the best, here are some alternate ways to answer the first question:

foreach (var toRemove in Details.Where(cityDetail => cityDetail.Text == null || string.IsNullOrEmpty(cityDetail.Text.TextWithHtml)))
    Details.Remove(toRemove);

foreach (var toRemove in (from cityDetail in Details
                              where cityDetail.Text == null || string.IsNullOrEmpty(cityDetail.Text.TextWithHtml)
                              select cityDetail))
    Details.Remove(toRemove);

(from cityDetail in Details
where cityDetail.Text == null || string.IsNullOrEmpty(cityDetail.Text.TextWithHtml)
select Details.Remove(cityDetail)).ToArray();

Upvotes: 1

YavgenyP
YavgenyP

Reputation: 2123

Your first question can be solved by using this "query":

Details = Details.Where(cityDetail=>cityDetail.Text != null && !string.IsNullOrEmpty(cityDetail.Text.TextWithHtml)).ToList();

This will override ur details var and with the new list, including only the non empty items.


As of ur second question - its not really clear what u want to do, and you need to provide us with some more details/ explanations

Edit:
IEnumerable(T) represents a read only collection, which means it doesnt support removing items by definition. Of course you can add ur own RemoveWhere extension method, but it will essentially be doing the same thing ive done here

Upvotes: 1

Related Questions