Nikola Sivkov
Nikola Sivkov

Reputation: 2852

C# combine two different sets of lists for iteration

I have lists of two Shapes - Rectangles and Circles. They both share 3 common properties - ID , Type and Bounds

Circles have 2 extra properties - Range and Center

How can i join lists of each type into a single list so i can iterate over them so i don't have to type two foreach cycles

Could this be donne in a better way than combining the lists ?

public interface IRectangle
{
    string Id { get; set; }
    GeoLocationTypes Type { get; set; }
    Bounds Bounds { get; set; }
}

public class Rectangle : IRectangle
{
    public string Id { get; set; }

    public GeoLocationTypes Type { get; set; }

    public Bounds Bounds { get; set; }
}


public interface ICircle
{
    string Id { get; set; }
    GeoLocationTypes Type { get; set; }
    Bounds Bounds { get; set; }
    float Radius { get; set; }
    Coordinates Center { get; set; }
}

public class Circle : ICircle
{
    public string Id { get; set; }

    public GeoLocationTypes Type { get; set; }


    public Bounds Bounds { get; set; }

    public float Radius { get; set; }

    public Coordinates Center { get; set; }
}

public class Bounds
{
    public Coordinates NE { get; set; }

    public Coordinates SW { get; set; }
}

public class Coordinates
{
    public float Lat { get; set; }

    public float Lng { get; set; }
}

Upvotes: 1

Views: 549

Answers (5)

Jodrell
Jodrell

Reputation: 35716

How about this

var merged = Rectagles.Select(r => new { 
        r.Id, 
        r.Type, 
        r.Bounds,
        Radius = float.NaN,
        Centre = default(Coordinates) })
    .Concat(Circles.Select(c => new {
        c.Id, 
        c.Type, 
        c.Bounds,
        c.Radius,
        c.Centre }));

it gives a list of enumerable of an anonymous type that exposes the required information.


EDIT

To my amazement this actually seems to compile. So there is a solution that works without defining a common interface. However for anything but the quick and dirty I would consider polymorphic over anonymous.

Upvotes: 1

NominSim
NominSim

Reputation: 8511

You could make them each use an IShape interface, or you could iterate over Objects and cast.

public interface IShape
{
    string Id { get; set; }
    GeoLocationTypes Type { get; set; }
    Bounds Bounds { get; set; }
}

public interface IRectangle : IShape { }

public class Rectangle : IRectangle
{
    // No change
}


public interface ICircle : IShape
{
    float Radius { get; set; }
    Coordinates Center { get; set; }
}

public class Circle : ICircle
{
    // No change
}

public class Bounds
{
    // No change
}

public class Coordinates
{
    // No change
}

There is also the Zip function that will allow you to enumerate over all of them.

An example:

var numbers= new [] { 1, 2, 3, 4 };
var words = new [] { "one", "two", "three" };

var numbersAndWords = numbers.Zip(words, (n, w) => new { Number = n, Word = w });
foreach(var nw in numbersAndWords)
{
    Console.WriteLine(nw.Number + nw.Word);
}

Upvotes: 2

Oded
Oded

Reputation: 499002

Make both IRectangle and ICircle inherit from a shared type - say IShape.

A List<IShape> will then be able to take any IRectangle and ICircle types and their inheriting types.

Since both IRectangle and ICircle share a number of properties, you can do this:

public interface IShape
{
    string Id { get; set; }
    GeoLocationTypes Type { get; set; }
    Bounds Bounds { get; set; }
}

public interface ICircle : IShape
{
    float Radius { get; set; }
    Coordinates Center { get; set; }
}

public interface IRectangle : IShape
{
}

Upvotes: 6

Jon Egerton
Jon Egerton

Reputation: 41549

Make an interface IShape that contains the common properties, then implement that as well as ICircle and IRectangle. (You could also use a base class that has the properties).

You should them be able to join list of Circles and Rectangles to get a list of IShapes.

Upvotes: 5

Prescott
Prescott

Reputation: 7412

You could further add an interface

public interface IShape
{
    string Id;
    GeoLocationTypes Type;
    Bounds Bounds;
}

Upvotes: 3

Related Questions