1

I am trying to check duplicate ID in two lists using LINQ query in C#. Here is the code:

List<DistributionStandardPackingUnitItems> itemList = new List<DistributionStandardPackingUnitItems>();
List<DistributionStandardPackingUnitItems> prodVariantDetail = new List<DistributionStandardPackingUnitItems>();
private List<DistributionStandardPackingUnitItems> tempDistSPUI
    {
        get
        {
            if (ViewState["tempDistSPUI"] == null)
            {
                return new List<DistributionStandardPackingUnitItems>();
            }
            else
            {
                return (List<DistributionStandardPackingUnitItems>)ViewState["tempDistSPUI"];
            }
        }
        set
        {
            ViewState["tempDistSPUI"] = value;
        }
    }
itemList = this.tempDistSPUI;
        for (int j = 0; j < itemList.Count; j++)
        {
            if (!prodVariantDetail.Any(i => i.id == itemList[j].id))
            {
                prodVariantDetail.Add(itemList[j]);
            }
        }

However, the prodVariantDetail list still contains duplicate ID. I wonder is there any other LINQ query like Where to fix this? Thanks in advance.

EDIT

 protected void lbnAdd_Click(object sender, EventArgs e)
    {
        List<DistributionStandardPackingUnitItems> prodVariantDetail = new List<DistributionStandardPackingUnitItems>();

        int packagesNeeded = prodPackBLL.getPackagesNeededByDistributionID(distributionID);

        // get the last product variant IDs from ViewState
        prodVariantIDList = this.SelectedVariantDetailIDs;

        foreach (RepeaterItem ri in Repeater1.Items)
        {
            GridView gvProduct = (GridView)ri.FindControl("gvProduct");
            foreach (GridViewRow gr in gvProduct.Rows)
            {
                CheckBox cb = (CheckBox)gr.FindControl("cbCheckRow");
                //Prevent gvFinalised to store duplicate products
                if (cb.Checked && !prodVariantIDList.Any(i => i == gvProduct.DataKeys[gr.RowIndex].Value.ToString()))
                {
                    // add the corresponding DataKey to idList
                    prodVariantIDList.Add(gvProduct.DataKeys[gr.RowIndex].Value.ToString());
                }
            }
        }

        for (int i = 0; i < prodVariantIDList.Count; i++)
        {
            prodVariantDetail.Add(packBLL.getProdVariantDetailByID(prodVariantIDList[i]));
        }

        //Check if itemList and prodVariantDetail list contains any duplicate records
        for (int j = 0; j < tempDistSPUI.Count; j++)
        {
            if (!prodVariantDetail.Any(i => i.id == tempDistSPUI[j].id))
            {
                prodVariantDetail.Add(tempDistSPUI[j]);
            }
        }

        gvFinalised.DataSource = prodVariantDetail;
        gvFinalised.DataBind();

        foreach (GridViewRow gr in gvFinalised.Rows)
        {
            //Get the product packaging quantity by productName
            string name = gr.Cells[1].Text;
            int productQuantity = packBLL.getProductQuantityByName(name, distributionID);
            TextBox tb = (TextBox)gr.Cells[5].FindControl("tbQuantity");

            if (productQuantity == 0)
            {
                tb.Text = productQuantity.ToString();
            }
            else
            {
                tb.Text = (productQuantity / packagesNeeded).ToString();
            }
        }

        // save prodVariantIDList to ViewState
        this.SelectedVariantDetailIDs = prodVariantIDList;
    }
  • 1
    Your code is not clear, could you please correct your code after the `tempDistSPUI` property? – Warlock Feb 05 '14 at 08:06
  • Possible the problem of duplication is related to a thread concurrency, your LINQ is OK. – Warlock Feb 05 '14 at 08:10
  • The code inside the `for` block is correctly avoiding duplicates from `itemList`, but it's not clear what happens to `prodVariantDetail` BEFORE the `for` block. It's possible that `prodVariantDetail` already contains duplicates BEFORE the `for` block. – ekad Feb 05 '14 at 10:09
  • @ekad The prodVariantDetail is taking data from the prodIDList which I check row from another gridview. would you mind to help me take a look at the edited portion? –  Feb 05 '14 at 10:12
  • I did a check for prodIDList before adding it into prodVariantDetail. –  Feb 05 '14 at 10:18
  • Are you sure `prodVariantDetail` doesn't contain duplicates BEFORE `for (int j = 0; j < tempDistSPUI.Count; j++)`? Please set a break point there and check. – ekad Feb 05 '14 at 10:28
  • Yeah I check already. the prodVariantDetail does not contains any duplicate because that list is just taking the row which checked from another gridview –  Feb 05 '14 at 10:43

4 Answers4

2
var toAdd = itemList.Where(i => !prodVariantDetail.Any(p => p.Id == i.Id));
var query = prodVariantDetail.Concat(toAdd);
w.b
  • 11,026
  • 5
  • 30
  • 49
0

You can try this

var Gdupes= itemList.GroupBy(x => new {x.ID}).Where(x => x.Skip(1).Any()).ToList();
List<DistributionStandardPackingUnitItems> dupes = Gdupes.SelectMany(x => x).ToList();
prodVariantDetail= itemList.Except(dupes).ToList();

Code not tested

pravprab
  • 2,301
  • 3
  • 26
  • 43
  • So I just replace the whole for loop with this? –  Feb 05 '14 at 09:29
  • @Gwen Yes , You can try , First line selects duplicates from List itemList to Gdupes grupby. then we take it to List dupes. Then copy itemList to prodVariantDetail except dupes – pravprab Feb 05 '14 at 09:33
  • It still contain duplicate record somehow. –  Feb 05 '14 at 10:01
0

Here is a common solution for your problem:

targetItems.AddRange(sourceItems.DistictBy(item => item.Id));

In your case sourceItems is itemList and targetItems is prodVariantDetail.

There are different implementations of the DistictBy method:

  1. You can apply Distinct LINQ from System.Linq.

  2. Use a custom DistictBy method (for example from MoreLinq).

Your problem in this lines of code:

for (int i = 0; i < prodVariantIDList.Count; i++)
{
    prodVariantDetail.Add(packBLL.getProdVariantDetailByID(prodVariantIDList[i]));
}
Community
  • 1
  • 1
Warlock
  • 7,321
  • 10
  • 55
  • 75
  • would you mind to show me some example? Cause I am still confused about it –  Feb 05 '14 at 09:28
  • @Gwen you can find examples by following links, which I provided. BTW I prefer the `DistinctBy` method. But before using this you should make code refactoring because it's not readable as well as not understandable. Just try to split the Click method into short methods and you will find the reason of items duplication. – Warlock Feb 05 '14 at 16:37
0

you can use a GroupJoin for a particular ID is duplicated

IEnumerable<DistributionStandardPackingUnitItems> toAdd  = (from first in prodVariantDetail
        join second in itemList
        on first.Id equals second.Id
        into matches
        where matches.Any()
        select first).ToList();

Or you can use projection like

IEnumerable<DistributionStandardPackingUnitItems> toAdd = (from first in prodVariantDetail
            join second in itemList
            on first.Id equals second.Id
            into matches
            where matches.Any()
            select new {Id=first.Id,Name=first.Name}).ToList();
Kaptan
  • 336
  • 2
  • 11