none
Linq to Objects Question RRS feed

  • Question

  • 2nd post, hopefully this one will take.

    I want to get a collction of Bonds and their associate collection of maturities where the maturity.matamount > 200000.

    edit: Of the filtered collection of bonds with mats > 200k, the maturiteis collection should be filtered as well, only showing mats > 200k.

    Here is a program.cs that has the class defs and a method to populate test data for the query.

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    
    namespace LinqToObjects
    {
    	class Program
    	{
    		static void Main(string[] args)
    		{
    			Program.QueryCollection();
    			Console.ReadLine();
    		}
    		public static void QueryCollection()
    		{
    			List<Bond> bonds = Program.BuildCollections();
    			//how do I get a list of Bonds that have a maturity.MatAmount > 200,000?
    		}
    		public static List<Bond> BuildCollections()
    		{
    			List<Bond> bonds = new List<Bond>();
    			Bond bond;
    
    			for (int i = 1; i <= 10; i++)
    			{
    				bond = new Bond() {ID = i, Title = "Bond Title " + i.ToString() };
    				for (int j = 1; j <= 10; j++)
    				{ 
    					bond.Maturities.Add(new Maturity(){ID = j, BondID = i, MatDate = DateTime.Today.AddDays(j), MatAmount = 152000 * j});
    				}
    
    				bonds.Add(bond);
    			}
    			return bonds;
    		}
    	}
    	public class Bond
    	{
    		public int ID { get; set; }
    		public string Title { get; set; }
    		public List<Maturity>  Maturities { get; set; }
    		public Bond()
    		{
    			Maturities = new List<Maturity>();
    		}
    	}
    	public class Maturity
    	{
    		public int ID { get; set; }
    		public int BondID { get; set; }
    		public DateTime MatDate { get; set; }
    		public int MatAmount { get; set; }
    	}
    
    }

     

    Thank you, Terrence


    • Edited by Terrence_ Thursday, September 27, 2012 2:46 PM
    Wednesday, September 26, 2012 11:06 PM

Answers

  • You'd use "Where" with "Any" to do this:

    public static void QueryCollection()
    {
        List<Bond> bonds = Program.BuildCollections();
        //how do I get a list of Bonds that have a maturity.MatAmount > 200,000?
        var largeBonds = bonds.Where(b => b.Maturities.Any(m => m.MatAmount > 200000));
    
        // If you need a list<T>, add .ToList()
    }


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    • Marked as answer by Terrence_ Thursday, September 27, 2012 6:33 PM
    Wednesday, September 26, 2012 11:46 PM
  • Hi Terrence_;

    Because the object Bond contains a internal list of Maturity when you query Bond you will always get back the Bond and all the Maturity objects associated with the Bond. If you want to return a Bond object with just a list of Maturity object that have a MatAmount greater then 200000 then you will need to create a new Bond object and add to the list of Maturities only those Maturity that meet the that requirement. The below query does that.

    var largeBonds = bonds.Where( b => b.Maturities
                          .Any( m => m.MatAmount > 200000))
                          .Select( bm => new Bond 
                              { 
                                  ID = bm.ID,
                                  Title = bm.Title,
                                  Maturities = bm.Maturities.Where( ma => ma.MatAmount > 200000).ToList()
                              });

      


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    • Marked as answer by Terrence_ Thursday, September 27, 2012 6:31 PM
    Thursday, September 27, 2012 3:29 PM

All replies

  • You'd use "Where" with "Any" to do this:

    public static void QueryCollection()
    {
        List<Bond> bonds = Program.BuildCollections();
        //how do I get a list of Bonds that have a maturity.MatAmount > 200,000?
        var largeBonds = bonds.Where(b => b.Maturities.Any(m => m.MatAmount > 200000));
    
        // If you need a list<T>, add .ToList()
    }


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    • Marked as answer by Terrence_ Thursday, September 27, 2012 6:33 PM
    Wednesday, September 26, 2012 11:46 PM
  • Reed, thanks so much for your answer.

    Now that I have tested it out, I wonder if you could tell me this.

    Your query works, but it includes all of the maturities associated with the bonds that have maturities > 200000.

    I only want to see the maturities in the Bond.Maturities collection with MatAmount > 200000.

    So its kind of like filter for the maturities > 200 and then show me the Bonds and those maturities.


    Thank you, Terrence


    • Edited by Terrence_ Thursday, September 27, 2012 2:26 AM
    Thursday, September 27, 2012 2:24 AM
  • Hi Terrence_;

    Because the object Bond contains a internal list of Maturity when you query Bond you will always get back the Bond and all the Maturity objects associated with the Bond. If you want to return a Bond object with just a list of Maturity object that have a MatAmount greater then 200000 then you will need to create a new Bond object and add to the list of Maturities only those Maturity that meet the that requirement. The below query does that.

    var largeBonds = bonds.Where( b => b.Maturities
                          .Any( m => m.MatAmount > 200000))
                          .Select( bm => new Bond 
                              { 
                                  ID = bm.ID,
                                  Title = bm.Title,
                                  Maturities = bm.Maturities.Where( ma => ma.MatAmount > 200000).ToList()
                              });

      


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    • Marked as answer by Terrence_ Thursday, September 27, 2012 6:31 PM
    Thursday, September 27, 2012 3:29 PM
  • Another option would be to further break up my previous, ie:

    public static void QueryCollection()
    {
        List<Bond> bonds = Program.BuildCollections();
    
        var largeBonds = bonds.Where(b => b.Maturities.Any(m => m.MatAmount > 200000));
    
        var largeMaturities = largeBonds.Select(b => new { OriginalBond = b, LargeMaturities = b.Maturities.Where(m = > m.MatAmount > 200000) });
    
        foreach(var bond in largeMaturities)
        {
           Console.WriteLine("Bond {0} contains maturities:", bond.OriginalBond.Name);
           foreach(var mat in bond.LargeMaturities)
                Console.WriteLine("    Mat {0}: {1}", mat.MatName, mat.MatAmount);
        }
    }


    Reed Copsey, Jr. - http://reedcopsey.com
    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Thursday, September 27, 2012 4:27 PM
  • Reed, thank you for your excellent answers.

    Thank you, Terrence

    Thursday, September 27, 2012 6:31 PM
  • Fernado, thank you for your explaination and answer.


    Thank you, Terrence

    Thursday, September 27, 2012 6:33 PM
  •  

    Not a problem Terrence, glad I was able to help.

      


    Fernando (MCSD)

    If a post answers your question, please click "Mark As Answer" on that post and "Mark as Helpful".

    Thursday, September 27, 2012 6:38 PM