2

Say I have a class or a struct defined as so:

public class foo
{
   public int x;
   public int y;
}

or 

public struct bar
{
   public int x;
   public int y;
}

Say I have some array or list of objects, either an array of foo's or bar's. Now I want to create an array or list of the x's and/or y's. Is there a simple way to do this in C# that does not require iterating through every foo or bar of the array, and then adding the desired member variable to another array?

For example, this is how I am currently doing it:

//For some List<foo> fooList
//get the x's and store them to the array List<int> xList

foreach (var fooAtom in fooList)
{
   xList.Add(fooAtom.x);
}

Is there a faster/less coding way of doing this? Is there a construct within C# designed specifically for this? Is it different for classes vs. structs? Thanks.

4
  • 2
    You can use LINQ. var allMyXs = fooList.Select(f => f.x) Commented Jul 8, 2014 at 16:52
  • Well LINQ solution are beautiful, but pay attention to performance. Select is not faster than your current loop and if the fooList is large.... (And by the way it is still a loop) Commented Jul 8, 2014 at 16:59
  • So does the time differential increase linearly with the size of the list? Commented Jul 8, 2014 at 17:00
  • @Iowa15 No. There is some marginal overhead but it does not grow with your list. Commented Jul 8, 2014 at 17:43

3 Answers 3

3

You could use LINQ query:

Int32[] xArray = fooList.Select(fooItem => fooItem.x).ToArray();

This LINQ query will work the same way for both the classes and structs. But struct values can be boxed in some cases and they will be copied multiple times(they are structs at the end - passed by value) - that all will cause possible overhead for huge structures with multiple LINQ operations upon them.

Also take into account that LINQ is not the tool for every possible situation. Sometimes plain for(while) loop will be much more readable and will provide greater performance.

Sign up to request clarification or add additional context in comments.

3 Comments

Read stackoverflow.com/questions/11344019/linq-and-lambda-expression and msdn.microsoft.com/en-us/library/bb397687.aspx. In short: each item in your list will be represented as fooItem, and from each this fooItem the .x field will be taken, and all those x fields will be united in one array.
This involves no boxing at all. It does copy them, which is entirely different. (And also what the OP specifically said he didn't want to do.)
@Iowa15 Note that by doing ToArray(), you're making a new collection of integers, and it no longer remains up to date with the original fooList. If you simply use var allXs = fooList.Select(f => f.x);, allXs will stay "up to date" when you add or remove members from fooList (since it is basically an abstraction of an iteration over fooList)
1

If they have something in common, you could also create an itnerface

public interface IFooBarable
{
    int x;
    int y;
}

and then your collection would just be a List<IFooBarable> in which you could hold your both Foo and Bar objects, and they could be accessed same way.

Comments

1

I would make a base class or interface that has the x and y properties. This could allow for more flexibility in iterating the collections:

public interface IHasXY { int x { get; } int y { get; } }

public class Foo : IHasXY { public int x { get; set; } public int y { get; set; } }
public struct Bar : IHasXY { public int x { get; set; } public int y { get; set; } }

Then you can even concat foo and bar collections:

var allXs = fooList.Concat(barList).Select(o => o.x).ToArray();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.