Fruit basket, how to use Linq to view from basket or fruit perspective?

The question is related to financial products, interest rates, and two properties that determine what interest a particular product is. But I think the fruits and baskets are easier to visualize for this.

First, we have fruit. Fruits can be of a certain size (small, medium, large) and color (red, green, blue). These will be two different enumerations. The baskets will contain all kinds of fruits, but none of them will be identical in color or shape. But every combination will be in the basket. Since we have three sizes and three colors, we will end up with 9 pieces of fruit in each basket. If we had 4 colors, we would have 12 pieces.

We store information about the shopping cart in the shopping cart. Each basket has a Dictionary <{Size, Color}, Fruit> that defines all the pieces of fruit in the basket. However, this dictionary cannot be completely filled, in which case all other combinations are apples. The dictionary contains only fruits of a different kind. (Although they may contain apples too.) Next to apples, we also have pears and bananas. Yes, they can be red, but I would have wondered what kind of paint was used to make them red. Remember, this is just to visualize the problem. :-)

Anyway, I now have a basket list with a basket list of fruits. Default apples, pears, or bananas if they are in the dictionary. But I need to look at the information from a different angle.

I need to convert this structure to a list of fruits and fruits in baskets where they can be found and the sizes and colors of specific fruits. So bananas are in basket 1 ({small, yellow}, {small, red}, {medium, red}), basket 3 (...), basket 4, 8 and 10. Same with pears, t have a yellow pear in basket 1 as it is already defined for the banana.

I have a big advantage: none of these structures have been defined yet! However, I need a cart view as a way to present information to the transformation process. And I need the Fruit view for further calculations, since I need to do some extra math based only on the fruit itself, not their size or color or the basket where they are ...

So, any good suggestions for the structure before and after the conversion, and how to do the conversion itself using Linq in C #?


In reality, baskets are products. Size and color are slight deviations from products. The fruits are interest rates, and I only need this rate for the math. By grouping the product by interest rate, I can reduce the number of calculations to a few. We deal with more than 1600 products for each product (10x10) 100 different options, for a total of 160,000 interest rates. The rates themselves usually range from 3 to 7.5% and are rounded to 1/20%. So about 90 different bets result in 90 calculations instead of 160,000 calculations ...

And I need to convince the management to take this step because they are afraid that it works a lot, becomes unreadable or is difficult to maintain.


Based on the interest rate, you can calculate how much a person can get a loan based on how much they want to spend per month on a product with certain conditions. This optimization will allow me to compare different products much faster. Wish I was the first in the company to notice this interesting optimization! :-)
+2


source to share


1 answer


Well, once I started, I had to write all the code. Maybe it doesn't solve your main problem, but I think it is nailing the fruit basket.

public enum FruitSize{Small, Medium, Large}
public enum FruitColor {Red, Green, Blue}

  // immutable struct is important for use as dictionary keys
public struct FruitDescription
{
    readonly FruitSize _size;
    public FruitSize Size {get{return _size;}}
    readonly FruitColor _color;
    public FruitColor Color { get { return _color; } }
    public FruitDescription(FruitSize size, FruitColor color)
    {
        _size = size;
        _color = color;
    }
}
    //abstract parent class ...
public abstract class Fruit
{ public FruitDescription Description {get;set;} }
    //... and children
public class Apple : Fruit{}
public class Banana : Fruit{}
public class Pear : Fruit{}

public class Basket
{
    private Dictionary<FruitDescription, Fruit> internalFruits =
        new Dictionary<FruitDescription, Fruit>();

    public void AddFruit(Fruit addme)
    {
        internalFruits[addme.Description] = addme;
    }

    public IEnumerable<FruitDescription> AllDescriptions()
    {
        foreach (FruitSize size in Enum.GetValues(typeof(FruitSize)))
        {
            foreach (FruitColor color in Enum.GetValues(typeof(FruitColor)))
            {
                FruitDescription desc = new FruitDescription(size, color);
                yield return desc;
            }
        }
    }

    public Apple GetDefaultApple(FruitDescription desc)
    {
        return new Apple() { Description = desc };
    }

    public IEnumerable<Fruit> GetFruits()
    {
        IEnumerable<Fruit> result = AllDescriptions()
            .Select(desc =>
              internalFruits.ContainsKey(desc) ?
              internalFruits[desc] :
              GetDefaultApple(desc));
        return result;
    }
}

public class Pair<T, U>
{
    public T First { get; set; }
    public U Second { get; set; }
}

public class TestClass
{
    public static void Test()
    {
        Basket b1 = new Basket();
        b1.AddFruit(new Banana() { Description =
            new FruitDescription(FruitSize.Medium, FruitColor.Blue) });
        b1.AddFruit(new Banana() { Description =
            new FruitDescription(FruitSize.Medium, FruitColor.Green) });

        Basket b2 = new Basket();
        b2.AddFruit(new Pear() { Description =
            new FruitDescription(FruitSize.Medium, FruitColor.Green) });

        List<Basket> source = new List<Basket>();
        source.Add(b1);
        source.Add(b2);

        //the main event - a query.
        List<Pair<Fruit, Basket>> result =
        (
          from basket in source
          from fruit in basket.GetFruits()
          select new Pair<Fruit, Basket>()
          { First = fruit, Second = basket }
        ).ToList();

        //a second results structure for fun
        ILookup<Type, Basket> resultByType = result.ToLookup
        (
            p => p.First.GetType(),
            p => p.Second
        );

        Console.WriteLine("Number of fruit: {0}",
            result.Count);
        Console.WriteLine("Number of apples: {0}",
            resultByType[typeof(Apple)].Count());
        Console.WriteLine("Number of baskets with apples: {0}",
            resultByType[typeof(Apple)].Distinct().Count());
        Console.WriteLine("Number of bananas: {0}",
            resultByType[typeof(Banana)].Count());
        Console.WriteLine("Number of baskets with bananas: {0}",
            resultByType[typeof(Banana)].Distinct().Count());
    }

}

      



With these results:

Number of fruit: 18
Number of apples: 15
Number of baskets with apples: 2
Number of bananas: 2
Number of baskets with bananas: 1

      

+2


source







All Articles