开发者

c# Linq differed execution challenge - help needed in creating 3 different lists

开发者 https://www.devze.com 2023-02-17 10:06 出处:网络
I am trying to create 3 different lists (1,2,3) from 2 existing lists (A,B). The 3 lists need to identify the following relationships.

I am trying to create 3 different lists (1,2,3) from 2 existing lists (A,B).

The 3 lists need to identify the following relationships.

  • List 1 - the items that are in list A and not in list B
  • List 2 - the items that are in list B and not in list A
  • List 3 - the items that are in both lists.

I then want to join all the lists together into one list.

My problem is that I want to identify the differences by adding an enum identifying the relationship to the items of each list. But by adding the Enum the Except Linq function does not identify the fact (obviously) that the lists are the same. Because the Linq queries are differed I can not resolve this by changing the order of my statements ie. identify the the lists and then add the Enums.

This is the code that I have got to (Doesn't work properly)

There might be a better approach.

        List<ManufactorListItem> manufactorItemList =
           manufactorRepository.GetManufactorList();

        // Get the Manufactors from the Families repository
        List<ManufactorListItem> familyManufactorList =
            this.familyRepository.GetManufactorList(familyGuid);

        // Identify Manufactors that are only found in the Manufactor Repository
        List<ManufactorListItem> inManufactorsOnly =
            manufactorItemList.Except(familyManufactorList).ToList();

        // Mark them as (Parent Only)
        foreach (ManufactorListItem manOnly in inManufactor开发者_开发技巧sOnly) {
            manOnly.InheritanceState = EnumInheritanceState.InParent;
        }

        // Identify Manufactors that are only found in the Family Repository
        List<ManufactorListItem> inFamiliesOnly =
            familyManufactorList.Except(manufactorItemList).ToList();

        // Mark them as (Child Only)
        foreach (ManufactorListItem famOnly in inFamiliesOnly) {
            famOnly.InheritanceState = EnumInheritanceState.InChild;
        }

        // Identify Manufactors that are found in both Repositories
        List<ManufactorListItem> sameList =
            manufactorItemList.Intersect(familyManufactorList).ToList();

        // Mark them Accordingly
        foreach (ManufactorListItem same in sameList) {
            same.InheritanceState = EnumInheritanceState.InBoth;
        }

        // Create an output List
        List<ManufactorListItem> manufactors = new List<ManufactorListItem>();

        // Join all of the lists together.
        manufactors = sameList.Union(inManufactorsOnly).
            Union(inFamiliesOnly).ToList();

Any ideas hot to get around this? Thanks in advance


You can make it much simplier:

List<ManufactorListItem> manufactorItemList = ...;
List<ManufactorListItem> familyManufactorList = ...;
var allItems = manufactorItemList.ToDictionary(i => i, i => InheritanceState.InParent);

foreach (var familyManufactor in familyManufactorList)
{
    allItems[familyManufactor] = allItems.ContainsKey(familyManufactor) ?
                                 InheritanceState.InBoth : 
                                 InheritanceState.InChild;
}

//that's all, now we can get any subset items:  

var inFamiliesOnly = allItems.Where(p => p.Value == InheritanceState.InChild).Select(p => p.Key);
var inManufactorsOnly = allItems.Where(p => p.Value == InheritanceState.InParent).Select(p => p.Key);
var allManufactors = allItems.Keys;


This seems like the simplest way to me:

(I'm using the following Enum for simplicity:

public enum ContainedIn
{
    AOnly,
    BOnly,
    Both
}

)

var la = new List<int> {1, 2, 3};
var lb = new List<int> {2, 3, 4};

var l1 = la.Except(lb)
           .Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.AOnly));
var l2 = lb.Except(la)
           .Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.BOnly));
var l3 = la.Intersect(lb)
           .Select(i => new Tuple<int, ContainedIn>(i, ContainedIn.Both));

var combined = l1.Union(l2).Union(l3);

So long as you have access to the Tuple<T1, T2> class (I think it's a .NET 4 addition).


If the problem is with the Except() statement, then I suggest you use the 3 parameter override of Except in order to provide a custom IEqualityComparer<ManufactorListItem> compare which tests the appropriate ManufactorListItem fields, but not the InheritanceState.

e.g. your equality comparer might look like:

public class ManufactorComparer : IEqualityComparer<ManufactorListItem>  { 
  public bool Equals(ManufactorListItem x, ManufactorListItem y)  { 
    // you need to write a method here that tests all the fields except InheritanceState 
  }  
  public int GetHashCode(ManufactorListItem obj)  { 
    // you need to write a simple hash code generator here using any/all the fields except InheritanceState
  } 
}

and then you would call this using code a bit like

// Identify Manufactors that are only found in the Manufactor Repository
List<ManufactorListItem> inManufactorsOnly =
        manufactorItemList.Except(familyManufactorList, new ManufactorComparer()).ToList();
0

精彩评论

暂无评论...
验证码 换一张
取 消