0

I have a c# object:

var obj = new Item { xcoords="1,2,3", ycoords="5,6,7", zcoords="8,9,4" }

So I want to split this into an array like following:

[
   new Item2 { x=1, y=5, z=8 },
   new Item2 { x=2, y=6, z=9 },
   new Item2 { x=3, y=7, z=4 }
]

Can I do this using Linq? or another way in c#?

7
  • That looks remarkably JSON-like, save for the property names being unquoted. Do you actually want JSON? Commented Jun 20, 2022 at 13:01
  • not json, it shout be c# object, the object array is after split operation. Commented Jun 20, 2022 at 13:02
  • 1
    @barteloma What happens if you get an uneven number of x,y,z? For example, xcoords has 3, ycoords has 2, and zcoords has 4? Also, is Item2 a class or struct you have declared? Commented Jun 20, 2022 at 13:03
  • What c# version are you on? Commented Jun 20, 2022 at 13:04
  • 1
    is xcoords actually string, or just laziness and you are dealing with int arrays? Commented Jun 20, 2022 at 13:05

3 Answers 3

1

Let's create a helper method (either as separate method or as local function):

static IEnumerable<int> ToInts(string s) => s.Split(',').Select(p => Int32.Parse(p));

Putting things together:

var obj = new Item { xcoords = "1,2,3", ycoords = "5,6,7", zcoords = "8,9,4" };

var result = ToInts(obj.xcoords)
    .Zip(ToInts(obj.ycoords), ToInts(obj.zcoords))
    .Select(t => new Item2{ x = t.First, y = t.Second, z = t.Third });

Note: this overload of Zip (since .NET 6?, the doc is wrong on this point) produces tuples with 3 elements named First, Second and Third.

You can append a .ToArray() if you need an array of Coord.


Test assuming that ToString is overridden like this in Item2:

public override string ToString() => $"[{x}, {y}, {z}]";
foreach (var item in result) {
    Console.WriteLine(item);
}

yields:

[1, 5, 8]
[2, 6, 9]
[3, 7, 4]
Sign up to request clarification or add additional context in comments.

Comments

1

You don't need LINQ here if coords number is static.

var obj = new Item { xcoords="1,2,3", ycoords="5,6,7", zcoords="8,9,4" };

var xcoords = obj.xcoords.Split(',');
var ycoords = obj.ycoords.Split(',');
var zcoords = obj.zcoords.Split(',');

var result = new Item2[]
{
    new Item2 { x = int.Parse(xcoords[0]), y = int.Parse(ycoords[0]), z = int.Parse(zcoords[0]) },
    new Item2 { x = int.Parse(xcoords[1]), y = int.Parse(ycoords[1]), z = int.Parse(zcoords[1]) },
    new Item2 { x = int.Parse(xcoords[2]), y = int.Parse(ycoords[2]), z = int.Parse(zcoords[2]) },
};

If coords number is dynamic but same for x, y and z then simple "for" loop may resolve the problem.

var obj = new Item { xcoords="1,2,3,4", ycoords="5,6,7,8", zcoords="8,9,4,10" };

var xcoords = obj.xcoords.Split(',');
var ycoords = obj.ycoords.Split(',');
var zcoords = obj.zcoords.Split(',');

var result = new Item2[xcoords.Length];

for (var i = 0; i < xcoords.Length; i++)
{
    result[i] = new Item2
    { 
        x = int.Parse(xcoords[i]),
        y = int.Parse(ycoords[i]),
        z = int.Parse(zcoords[i])
    };
}

LINQ version (Requires .NET 6 or higher. In the previous versions Zip method takes only 2 collections at once.):

var obj = new Item { xcoords = "1,2,3,4", ycoords = "5,6,7,8", zcoords = "8,9,4,10" };

var result = Enumerable
    .Zip(
        obj.xcoords.Split(','),
        obj.ycoords.Split(','),
        obj.zcoords.Split(','),
        (x, y, z) => (x, y, z))
    .Select(
        coord => new Item2
        {
            x = int.Parse(coord.x),
            y = int.Parse(coord.y),
            z = int.Parse(coord.z)
        });

Comments

1

Linq approach https://dotnetfiddle.net/CHizmw

Item obj = new Item { xcoords = "1,2,3", ycoords = "5,6,7", zcoords = "8,9,4" };
Func<string, int[]> GetInt = value => value.Split(',').Select(int.Parse).ToArray();
var helper = new {  xc = GetInt(obj.xcoords), yc = GetInt(obj.ycoords), zc = GetInt(obj.zcoords) };
Item2[] obj2 = Enumerable.Range(0, helper.xc.Length).Select(o =>  new Item2() { x = helper.xc[o], y = helper.yc[o], z = helper.zc[o] }).ToArray();

2 Comments

In this solution string.Split method will be called more than it is required. Method result should be cashed to improve performance.
@DaniilPalii Updated - only 1 split per string

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.