Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. LINQ
  4. Multiple Unique Requirements

Multiple Unique Requirements

Scheduled Pinned Locked Moved LINQ
questioncsharpdatabaselinqbusiness
10 Posts 3 Posters 5 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    Lost User
    wrote on last edited by
    #1

    Is there a way to do this with out looping? Example: MyDataSet has 3 paramaters ParamA, ParamB, and ofcourse ParamC Currently I have to do this...

            var aUnique = data.Select(a => a.ParamA).Distinct();
    
            int count = 0;
            foreach (var paramA in aUnique )
            {
                //Get unique b
                var bUnique = data.Select(b => b.ParamB).Distinct();
                foreach (var paramB in bUnique)
                {
                    //Query with our current constraints
                    var results = from items in data
                                  where items.ParamA == paramA 
                                  where items.ParamB == paramB
                                  select items;
    
                    int cCount = data.Select(c => c.ParamC).Distinct().Count();
                    count += cCount ;
                }
            }
    

    I would like the same logic in a single LINQ statement if it can be done. The loop seems quite slow...

    ASCII stupid question, get a stupid ANSI

    L G 2 Replies Last reply
    0
    • L Lost User

      Is there a way to do this with out looping? Example: MyDataSet has 3 paramaters ParamA, ParamB, and ofcourse ParamC Currently I have to do this...

              var aUnique = data.Select(a => a.ParamA).Distinct();
      
              int count = 0;
              foreach (var paramA in aUnique )
              {
                  //Get unique b
                  var bUnique = data.Select(b => b.ParamB).Distinct();
                  foreach (var paramB in bUnique)
                  {
                      //Query with our current constraints
                      var results = from items in data
                                    where items.ParamA == paramA 
                                    where items.ParamB == paramB
                                    select items;
      
                      int cCount = data.Select(c => c.ParamC).Distinct().Count();
                      count += cCount ;
                  }
              }
      

      I would like the same logic in a single LINQ statement if it can be done. The loop seems quite slow...

      ASCII stupid question, get a stupid ANSI

      L Offline
      L Offline
      Lost User
      wrote on last edited by
      #2

      Is this the same?

      var distinct = (from item in data
      select new { item.ParamA, item.ParamB, item.ParamC}).Distinct();

      int count = distinct.Count();

      ASCII stupid question, get a stupid ANSI

      D 1 Reply Last reply
      0
      • L Lost User

        Is there a way to do this with out looping? Example: MyDataSet has 3 paramaters ParamA, ParamB, and ofcourse ParamC Currently I have to do this...

                var aUnique = data.Select(a => a.ParamA).Distinct();
        
                int count = 0;
                foreach (var paramA in aUnique )
                {
                    //Get unique b
                    var bUnique = data.Select(b => b.ParamB).Distinct();
                    foreach (var paramB in bUnique)
                    {
                        //Query with our current constraints
                        var results = from items in data
                                      where items.ParamA == paramA 
                                      where items.ParamB == paramB
                                      select items;
        
                        int cCount = data.Select(c => c.ParamC).Distinct().Count();
                        count += cCount ;
                    }
                }
        

        I would like the same logic in a single LINQ statement if it can be done. The loop seems quite slow...

        ASCII stupid question, get a stupid ANSI

        G Offline
        G Offline
        Gideon Engelberth
        wrote on last edited by
        #3

        It looks like you are trying to group the items to me. If you are trying to find how many items there are for each combination of (A, B, C), a Group By should work.

        L 1 Reply Last reply
        0
        • G Gideon Engelberth

          It looks like you are trying to group the items to me. If you are trying to find how many items there are for each combination of (A, B, C), a Group By should work.

          L Offline
          L Offline
          Lost User
          wrote on last edited by
          #4

          I have not used group by. Can you give a simple example following my above requirements?

          ASCII stupid question, get a stupid ANSI

          1 Reply Last reply
          0
          • L Lost User

            Is this the same?

            var distinct = (from item in data
            select new { item.ParamA, item.ParamB, item.ParamC}).Distinct();

            int count = distinct.Count();

            ASCII stupid question, get a stupid ANSI

            D Offline
            D Offline
            Dan Mos
            wrote on last edited by
            #5

            no it is not the same.

            Collin Jasnoch wrote:

            ar distinct = (from item in data select new { item.ParamA, item.ParamB, item.ParamC}).Distinct();

            this will give you distinct groups of ParamA,B and C. but ParamA will not be unique. Ex: 1,2,3 and 1,3,2. As you can see A is not unique but the hole collection of Params is unique. [EDIT] Better said it won't work. I mean it will compile and execute but it won't give you distinct combinations of the 3 params because it doesn't know how to compare them. You need to supply the Distinct(IComparer); In fact here is one possible solution to your problem:

            //1) create a class
            public class ThreeParams{
            public int ParamA{get;set;}
            public int ParamB{get;set;}
            public int ParamC{get;set;}

                public override string ToString()
                {
                    return ParamA + "\\t" + ParamB + "\\t" + ParamC;
                }
            

            //you could Implement IEqutable in here or to provide more flexibility out of the class as
            //i did in listing/point 2)
            }

            //2) Create a IEqualityComparer for your class
            public class ParamsEqualityComparer : IEqualityComparer<ThreeParams>
            {
            //of course you can chage the implementation to suit your needs
            public bool Equals(ThreeParams a, ThreeParams b)
            {
            return a.ParamA.Equals(b.ParamA)
            || a.ParamB.Equals(b.ParamB)
            || a.ParamC.Equals(b.ParamC);
            }

                public int GetHashCode(ThreeParams a)
                {
                    return a.ToString().GetHashCode();
                }
            }
            

            //3) now all you have to do is:
            var distinct = (from item in data
            select item).Distinct( new ParamsEqualityComparer());
            //data is a list of ThreeSomething

            modified on Saturday, February 20, 2010 4:04 AM

            L 1 Reply Last reply
            0
            • D Dan Mos

              no it is not the same.

              Collin Jasnoch wrote:

              ar distinct = (from item in data select new { item.ParamA, item.ParamB, item.ParamC}).Distinct();

              this will give you distinct groups of ParamA,B and C. but ParamA will not be unique. Ex: 1,2,3 and 1,3,2. As you can see A is not unique but the hole collection of Params is unique. [EDIT] Better said it won't work. I mean it will compile and execute but it won't give you distinct combinations of the 3 params because it doesn't know how to compare them. You need to supply the Distinct(IComparer); In fact here is one possible solution to your problem:

              //1) create a class
              public class ThreeParams{
              public int ParamA{get;set;}
              public int ParamB{get;set;}
              public int ParamC{get;set;}

                  public override string ToString()
                  {
                      return ParamA + "\\t" + ParamB + "\\t" + ParamC;
                  }
              

              //you could Implement IEqutable in here or to provide more flexibility out of the class as
              //i did in listing/point 2)
              }

              //2) Create a IEqualityComparer for your class
              public class ParamsEqualityComparer : IEqualityComparer<ThreeParams>
              {
              //of course you can chage the implementation to suit your needs
              public bool Equals(ThreeParams a, ThreeParams b)
              {
              return a.ParamA.Equals(b.ParamA)
              || a.ParamB.Equals(b.ParamB)
              || a.ParamC.Equals(b.ParamC);
              }

                  public int GetHashCode(ThreeParams a)
                  {
                      return a.ToString().GetHashCode();
                  }
              }
              

              //3) now all you have to do is:
              var distinct = (from item in data
              select item).Distinct( new ParamsEqualityComparer());
              //data is a list of ThreeSomething

              modified on Saturday, February 20, 2010 4:04 AM

              L Offline
              L Offline
              Lost User
              wrote on last edited by
              #6

              OK that helps. I actually already have my object inherit from IQuatable so if I use a separate Comparer it seems I can get it to work the way I want. I am a bit confused by what you said though

              MDL=>Moshu wrote:

              this will give you distinct groups of ParamA,B and C. but ParamA will not be unique. Ex: 1,2,3 and 1,3,2. As you can see A is not unique but the hole collection of Params is unique.

              Maybe I was not originally doing what I want, but this sounds like what I am wanting. To explain a little more detail. The params are identifiers for product. ParamA is serialized (meaning there exists only one occurance of it for some product). So as an example lets say ParamA is "XXXX23" in one case and "XXXX24" in another. ParamB and ParamC are not serialized. Meaning that both "XXXX23" and "XXXX24" could have the same values for ParamB and/or ParamC but the actual product is different then. FOr example here are some entries. 1. ParamA = "XXXX24" ParamB = 1 ParamC = 32 2. ParamA = "XXXX24" ParamB = 2 ParamC = 32 3. ParamA = "XXXX23" ParamB = 2 ParamC = 32 4. ParamA = "XXXX23" ParamB = 2 ParamC = 32 5. ParamA = "XXXX24" ParamB = 1 ParamC = 31 What I want returned is items 1,2,(3/4), and 5. Note the only same product is 3 and 4 so one istance of their entry is returned. So is this what my current code is doing?

              ASCII stupid question, get a stupid ANSI

              D 1 Reply Last reply
              0
              • L Lost User

                OK that helps. I actually already have my object inherit from IQuatable so if I use a separate Comparer it seems I can get it to work the way I want. I am a bit confused by what you said though

                MDL=>Moshu wrote:

                this will give you distinct groups of ParamA,B and C. but ParamA will not be unique. Ex: 1,2,3 and 1,3,2. As you can see A is not unique but the hole collection of Params is unique.

                Maybe I was not originally doing what I want, but this sounds like what I am wanting. To explain a little more detail. The params are identifiers for product. ParamA is serialized (meaning there exists only one occurance of it for some product). So as an example lets say ParamA is "XXXX23" in one case and "XXXX24" in another. ParamB and ParamC are not serialized. Meaning that both "XXXX23" and "XXXX24" could have the same values for ParamB and/or ParamC but the actual product is different then. FOr example here are some entries. 1. ParamA = "XXXX24" ParamB = 1 ParamC = 32 2. ParamA = "XXXX24" ParamB = 2 ParamC = 32 3. ParamA = "XXXX23" ParamB = 2 ParamC = 32 4. ParamA = "XXXX23" ParamB = 2 ParamC = 32 5. ParamA = "XXXX24" ParamB = 1 ParamC = 31 What I want returned is items 1,2,(3/4), and 5. Note the only same product is 3 and 4 so one istance of their entry is returned. So is this what my current code is doing?

                ASCII stupid question, get a stupid ANSI

                D Offline
                D Offline
                Dan Mos
                wrote on last edited by
                #7

                Yeah I misunderstood what you wanted. Now, I don't know how you implemented the IEqualityComparer. So i don't know what it does. But what I showed in my previous post it doesn't do that. [Edit]It gives you only distinct combination where A is distinct so 1,2,4 but not 1,4,2.[/Edit] If I understood well you need to return distinct products and a product is distinct as long as ParamA is distinct or the combination of B and C is distinct if the ParamA is the same. This should do it:

                public bool Equals(ThreeParams a, ThreeParams b){
                if(a.ParamA == b.ParamA){
                if((a.ParamB == b.ParamB) && (a.ParamC == b.ParamC)){
                return true;
                }
                else{
                return false;
                }
                }
                return false;
                }

                modified on Monday, February 22, 2010 12:17 PM

                L 1 Reply Last reply
                0
                • D Dan Mos

                  Yeah I misunderstood what you wanted. Now, I don't know how you implemented the IEqualityComparer. So i don't know what it does. But what I showed in my previous post it doesn't do that. [Edit]It gives you only distinct combination where A is distinct so 1,2,4 but not 1,4,2.[/Edit] If I understood well you need to return distinct products and a product is distinct as long as ParamA is distinct or the combination of B and C is distinct if the ParamA is the same. This should do it:

                  public bool Equals(ThreeParams a, ThreeParams b){
                  if(a.ParamA == b.ParamA){
                  if((a.ParamB == b.ParamB) && (a.ParamC == b.ParamC)){
                  return true;
                  }
                  else{
                  return false;
                  }
                  }
                  return false;
                  }

                  modified on Monday, February 22, 2010 12:17 PM

                  L Offline
                  L Offline
                  Lost User
                  wrote on last edited by
                  #8

                  I still do not understand why the LINQ query I wrote doesn't do that.. Here is some test code... Simple form with a dataset getting initialized. Note that 7 is posted. Because there are 3 entires with "X1", 1, 1 and 2 entries with "X2", 2, 1 and numerous combinations inbetween. Total entries is 10. so (1,2), 3, 4, 5, 6,(7,8,9), 10 for a total of 7. So I seem to be getting what I would expect... Am I missing a case where I get an extra count or do not receive a count?

                  public partial class Form1 : Form
                  {
                      List<MyDataSet> dataSet;
                      public Form1()
                      {
                          InitializeComponent();
                      }
                  
                      private void bttnGo\_Click(object sender, EventArgs e)
                      {
                          FillDataSet();
                  
                  
                          var distinct = (from items in dataSet
                                          select new { SerializedParam = items.SerializedParam, NonSerializedParam2 = items.NonSerializedParam2, NonSerializedParam1 = items.NonSerializedParam1 }).Distinct();
                  
                          MessageBox.Show(distinct.Count().ToString());
                      }
                  
                      private void FillDataSet()
                      {
                          dataSet = new List<MyDataSet>();
                  
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X1",
                              NonSerializedParam1 = 1,
                              NonSerializedParam2 = 1
                          });
                  
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X1",
                              NonSerializedParam1 = 1,
                              NonSerializedParam2 = 1
                          });
                  
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X1",
                              NonSerializedParam1 = 1,
                              NonSerializedParam2 = 2
                          });
                  
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X1",
                              NonSerializedParam1 = 2,
                              NonSerializedParam2 = 1
                          });
                  
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X2",
                              NonSerializedParam1 = 1,
                              NonSerializedParam2 = 1
                          });
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X2",
                              NonSerializedParam1 = 1,
                              NonSerializedParam2 = 2
                          });
                          dataSet.Add(new MyDataSet()
                          {
                              SerializedParam = "X2",
                              NonSerializedParam1 = 2,
                              NonSerializedParam2 =
                  
                  D 1 Reply Last reply
                  0
                  • L Lost User

                    I still do not understand why the LINQ query I wrote doesn't do that.. Here is some test code... Simple form with a dataset getting initialized. Note that 7 is posted. Because there are 3 entires with "X1", 1, 1 and 2 entries with "X2", 2, 1 and numerous combinations inbetween. Total entries is 10. so (1,2), 3, 4, 5, 6,(7,8,9), 10 for a total of 7. So I seem to be getting what I would expect... Am I missing a case where I get an extra count or do not receive a count?

                    public partial class Form1 : Form
                    {
                        List<MyDataSet> dataSet;
                        public Form1()
                        {
                            InitializeComponent();
                        }
                    
                        private void bttnGo\_Click(object sender, EventArgs e)
                        {
                            FillDataSet();
                    
                    
                            var distinct = (from items in dataSet
                                            select new { SerializedParam = items.SerializedParam, NonSerializedParam2 = items.NonSerializedParam2, NonSerializedParam1 = items.NonSerializedParam1 }).Distinct();
                    
                            MessageBox.Show(distinct.Count().ToString());
                        }
                    
                        private void FillDataSet()
                        {
                            dataSet = new List<MyDataSet>();
                    
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X1",
                                NonSerializedParam1 = 1,
                                NonSerializedParam2 = 1
                            });
                    
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X1",
                                NonSerializedParam1 = 1,
                                NonSerializedParam2 = 1
                            });
                    
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X1",
                                NonSerializedParam1 = 1,
                                NonSerializedParam2 = 2
                            });
                    
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X1",
                                NonSerializedParam1 = 2,
                                NonSerializedParam2 = 1
                            });
                    
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X2",
                                NonSerializedParam1 = 1,
                                NonSerializedParam2 = 1
                            });
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X2",
                                NonSerializedParam1 = 1,
                                NonSerializedParam2 = 2
                            });
                            dataSet.Add(new MyDataSet()
                            {
                                SerializedParam = "X2",
                                NonSerializedParam1 = 2,
                                NonSerializedParam2 =
                    
                    D Offline
                    D Offline
                    Dan Mos
                    wrote on last edited by
                    #9

                    Collin Jasnoch wrote:

                    I still do not understand why the LINQ query I wrote doesn't do that.. Here is some test code...

                    But 7 is supposed to return so what is the problem? What LINQ query doesn't work? You mean your initial query? For your needs it just happens that it works. The compiler creates a default implementation for an anonymous type that enforce the combination of property(s), field(s) to be unique. OK. You're not selecting MyDataSet objects but you're selecting somethig like this:

                    internal class ???
                    {
                    public string PanleID{get;set;}
                    public int PartOnStrip {get;set;}
                    .....
                    }
                    //when you do something like select new{Bla ="Blah"}
                    //the compiler will automatically create an anonymous type/class for you.
                    //it knows you want to select a string in this case named Bla so it will create
                    //a class like this aprox.
                    internal class ???
                    {
                    public string Bla{get;set;}
                    }
                    //This is the magic behind the var keyword in a LINQ query.

                    That's why it works for your special need. I thought that you wanted distinct values for paramA but you don't. So ignore my first reply. Now: 1)If you modify your click event to something like this

                    private void bttnGo_Click(object sender, EventArgs e)
                    {
                    FillDataSet();
                    var distinct =
                    (from items in dataSet
                    select new MyDataSet//see the new MyDataSet added.
                    //Now it selects MyDataSet objects until now it selected
                    // an anonymous type.
                    {
                    SerializedParam = items.SerializedParam,
                    NonSerializedParam1 = items.NonSerializedParam2,
                    NonSerializedParam2 = items.NonSerializedParam1
                    }).Distinct();
                    MessageBox.Show(distinct.Count().ToString());//you'll get 10 all of them
                    //because it does not know how to compare them. On the internal
                    //annonymous type it enforeced the rule mentioned above.
                    }

                    L 1 Reply Last reply
                    0
                    • D Dan Mos

                      Collin Jasnoch wrote:

                      I still do not understand why the LINQ query I wrote doesn't do that.. Here is some test code...

                      But 7 is supposed to return so what is the problem? What LINQ query doesn't work? You mean your initial query? For your needs it just happens that it works. The compiler creates a default implementation for an anonymous type that enforce the combination of property(s), field(s) to be unique. OK. You're not selecting MyDataSet objects but you're selecting somethig like this:

                      internal class ???
                      {
                      public string PanleID{get;set;}
                      public int PartOnStrip {get;set;}
                      .....
                      }
                      //when you do something like select new{Bla ="Blah"}
                      //the compiler will automatically create an anonymous type/class for you.
                      //it knows you want to select a string in this case named Bla so it will create
                      //a class like this aprox.
                      internal class ???
                      {
                      public string Bla{get;set;}
                      }
                      //This is the magic behind the var keyword in a LINQ query.

                      That's why it works for your special need. I thought that you wanted distinct values for paramA but you don't. So ignore my first reply. Now: 1)If you modify your click event to something like this

                      private void bttnGo_Click(object sender, EventArgs e)
                      {
                      FillDataSet();
                      var distinct =
                      (from items in dataSet
                      select new MyDataSet//see the new MyDataSet added.
                      //Now it selects MyDataSet objects until now it selected
                      // an anonymous type.
                      {
                      SerializedParam = items.SerializedParam,
                      NonSerializedParam1 = items.NonSerializedParam2,
                      NonSerializedParam2 = items.NonSerializedParam1
                      }).Distinct();
                      MessageBox.Show(distinct.Count().ToString());//you'll get 10 all of them
                      //because it does not know how to compare them. On the internal
                      //annonymous type it enforeced the rule mentioned above.
                      }

                      L Offline
                      L Offline
                      Lost User
                      wrote on last edited by
                      #10

                      It is returning what I expected.. So I was just wondering why you said it was not the same. It makes sence what you have said though.. specifically the modifcation you made. Thank you!

                      ASCII stupid question, get a stupid ANSI

                      1 Reply Last reply
                      0
                      Reply
                      • Reply as topic
                      Log in to reply
                      • Oldest to Newest
                      • Newest to Oldest
                      • Most Votes


                      • Login

                      • Don't have an account? Register

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • World
                      • Users
                      • Groups