Solved

LINQ Query

Posted on 2011-09-16
9
356 Views
Last Modified: 2013-11-11
I can't seem to wrap my brain around what strikes me as very simple.

Assume I have these two simple tables (IEnumerables really)

Table1: Authorities (IEnumerable<AuthorityRow>)
Position     CanAuthorize
======================
CEO           MedicalTravel
CEO           BusinessTravel
CFO           MedicalTravel
CFO           BusinessTravel
HRLeader  MedicalTravel

Table2: MatchList (IEnumerable<MatchListRow>)
Authority
=============
MedicalTravel
BusinessTravel

How can I produce a list of Positions who have all the Authorities listed in MatchList?

In the example above, CFO and CEO should be produced, but not HR Leader.

I normally prefer the method-based syntax but I'm not too particular and would be just as pleased with query-based.

tk

0
Comment
Question by:tknudsen-qec
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
9 Comments
 
LVL 21

Expert Comment

by:naspinski
ID: 36550139
Untested, but this should work:
var matches = MatchList.Select(x => x.Authority);//gets a IEnumerable<string>
var results = Authorities.Where(x => matches.Contains(x.CanAuthorize));

Open in new window

0
 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36550335
That was pretty much identical to my first attempt naspinski, but it fails because "HR Leader" produces one match on "Medical" and therefore ends up in the results list with the others.  Tested as attached.

 
public class Authority
    {
      public Authority(string pos, string canauth)
      {
        Position = pos;
        CanAuthorize = canauth;
      }
      public string Position { get; set; }
      public string CanAuthorize { get; set; }
    }

    public class MatchList
    {
      public MatchList(string auth)
      {
        Authority = auth;
      }
      public string Authority { get; set; }
    }


	


    protected void Page_Load(object sender, EventArgs e)
    {
      List<Authority> Authorities = new List<Authority>();
      Authorities.Add(new Authority("CEO", "Medical"));
      Authorities.Add(new Authority("CEO", "Business"));
      Authorities.Add(new Authority("CFO", "Medical"));
      Authorities.Add(new Authority("CFO", "Business"));
      Authorities.Add(new Authority("HR Leader", "Medical"));

      List<MatchList> MatchLists = new List<MatchList>();
      MatchLists.Add(new MatchList("Medical"));
      MatchLists.Add(new MatchList("Business"));

      var matches = MatchLists.Select(x => x.Authority);//gets a IEnumerable<string>
      var results = Authorities.Where(x => matches.Contains(x.CanAuthorize));

    }

Open in new window


0
 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36550352
This is how I'd do it in T-SQL but I'm unsure of the translation to LINQ:

SELECT DISTINCT A.Position
FROM #Authorities A
INNER JOIN
(
      SELECT Distinct Position, Authority
      FROM #Authorities A
      CROSS JOIN #MatchList M
) M ON M.Authority = A.CanAuthorize AND M.Position = A.Position
0
DevOps Toolchain Recommendations

Read this Gartner Research Note and discover how your IT organization can automate and optimize DevOps processes using a toolchain architecture.

 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36551034
Scratch that, my query doesn't work either.
0
 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36551199
This seems to work but its not pretty.

 
// create a cartesian product of all possible position/authority combinations
      IEnumerable<Authority> product =
        from M in MatchLists
        from A in Authorities.Select( x => x.Position).Distinct()
        select new Authority(A, M.Authority);

      // get a list of positions that dont match back to our list of valid combinations
      IEnumerable<string> invalidpositions =
        from p in product
        join a in Authorities on new { p.CanAuthorize, p.Position } equals new { a.CanAuthorize, a.Position } into ps
        from a in ps.DefaultIfEmpty()
        where a == null
        select p.Position;

      // get a list of positions that arent in our list of non-matches
      IEnumerable<string> validpositions = (from a in Authorities
                                           where !invalidpositions.Any(x => x == a.Position)
                                           select a.Position).Distinct();

Open in new window


It emulates this SQL query:

   
SELECT DISTINCT Position
FROM #Authorities
WHERE Position NOT IN
(
	SELECT DISTINCT M.Position
	FROM
	(
		SELECT Distinct Position, Authority
		FROM #Authorities A
		CROSS JOIN #MatchList M
	) M
	LEFT OUTER JOIN #Authorities A ON M.Authority = A.CanAuthorize AND M.Position = A.Position
	WHERE A.Position IS NULL
)

Open in new window



Which, since it works and nobody has an alternative, will serve as the "answer".

Thx go to naspinski for making an effort however.

0
 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36560149
I've requested that this question be closed as follows:

Accepted answer: 0 points for tknudsen-qec's comment http:/Q_27312340.html#36551199

for the following reason:

Own solution works, no working alternatives provided.<br /><br />I'd be pleased to re-offer points (if permitted) if a better solution provided.
0
 
LVL 3

Accepted Solution

by:
nixkuroi earned 500 total points
ID: 36558469
Try this one:

List<Authority> Authorities = new List<Authority>();
      Authorities.Add(new Authority("CEO", "Medical"));
      Authorities.Add(new Authority("CEO", "Business"));
      Authorities.Add(new Authority("CFO", "Medical"));
      Authorities.Add(new Authority("CFO", "Business"));
      Authorities.Add(new Authority("HR Leader", "Medical"));

      List<string> MatchLists = new List<string>();
      MatchLists.Add("Medical");
      MatchLists.Add("Business");


      List<string> authsWithAll = Authorities.GroupBy(i => i.Position, (key, group) => group.First()).ToDictionary(d => d.Position, d => d).Keys.ToList().ToDictionary(d => d, d => Authorities.Where(w => w.Position == d).ToList().ConvertAll(c => c.CanAuthorize).ToList()).Where(w => MatchLists.Except((List<string>)w.Value).ToList().Count == 0 && ((List<string>)w.Value).Except(MatchLists).ToList().Count == 0).ToDictionary(d=>d.Key, d=>d.Value).Keys.ToList();
0
 
LVL 3

Author Comment

by:tknudsen-qec
ID: 36560150
nixkuroi's solution works.  Please cancel the close-request so I can offer points.
0
 
LVL 3

Author Closing Comment

by:tknudsen-qec
ID: 36560168
@nixkuroi:
Thanks, that seems to work fine.  Thanks for not pointing out that I invented a "string" class for MatchLists.  Not sure what I was thinking.
0

Featured Post

Learn by Doing. Anytime. Anywhere.

Do you like to learn by doing?
Our labs and exercises give you the chance to do just that: Learn by performing actions on real environments.

Hands-on, scenario-based labs give you experience on real environments provided by us so you don't have to worry about breaking anything.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
It was really hard time for me to get the understanding of Delegates in C#. I went through many websites and articles but I found them very clumsy. After going through those sites, I noted down the points in a easy way so here I am sharing that unde…
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
Add bar graphs to Access queries using Unicode block characters. Graphs appear on every record in the color you want. Give life to numbers. Hopes this gives you ideas on visualizing your data in new ways ~ Create a calculated field in a query: …

707 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question