I have an object "Compact" that consists of an ID and two arrays:
public class Compact
{
public int Id { get; set; }
public int[] Number { get; set; }
public double[] Value { get; set; }
public Compact(int id, int[] number, double[] value)
{
Id = id;
Number = number;
Value = value;
}
}
A list of Compact objects can be initialized like this:
List<Compact> c = new List<Compact>
{
new Compact(1, new int[] { 1, 2, 3 }, new double[] { 0.05, 0.02, 0.03 }),
new Compact(2, new int[] { 1, 2, 3 }, new double[] { 0.07, 0.01, 0.04 }),
new Compact(3, new int[] { 1, 2, 3 }, new double[] { 0.02, 0.025, 0.05 })
};
I am looking for an elegant way to flatten this object into the object "Flattened":
public class Flattened
{
public int Id { get; set; }
public int Number { get; set; }
public double Value { get; set; }
public Flattened(int id, int number, double value)
{
Id = id;
Number = number;
Value = value;
}
}
The result of the flattening would correspond to this:
List<Flattened> f = new List<Flattened>
{
new Flattened(1,1,0.05),
new Flattened(1,2,0.02),
new Flattened(1,3,0.03),
new Flattened(2,1,0.07),
new Flattened(2,2,0.01),
new Flattened(2,3,0.04),
new Flattened(3,1,0.02),
new Flattened(3,2,0.025),
new Flattened(3,3,0.05)
};
I am able to do the flattening using loops, but I am wondering whether there are more suited methods in terms of performance, like a Linq operation or a different collection-type?
CodePudding user response:
You can run simply for
loops.
List<Compact> ls = new List<Compact>
{
new Compact(1, new int[] { 1, 2, 3 }, new double[] { 0.05, 0.02, 0.03 }),
new Compact(2, new int[] { 1, 2, 3 }, new double[] { 0.07, 0.01, 0.04 }),
new Compact(3, new int[] { 1, 2, 3 }, new double[] { 0.02, 0.025, 0.05 })
};
List<Flattened> ls2 = new List<Flattened>();
foreach (Compact compact in ls)
{
for (var index = 0; index < compact.Number.Length; index )
{
ls2.Add(new Flattened(compact.Id, compact.Number[index], compact.Value[index]));
}
}
Note I have assumed that both arrays will have same number of items.
CodePudding user response:
Using LINQ, you can do
c.SelectMany(
x => x.Number.Zip(x.Value, (n, v) => new Flattened(x.Id, n, v))
).ToList()
SelectMany
does the flattening, Zip
, as its name suggests, "zips" the Number
and Value
arrays together, and apply the function (n, v) => new Flattened(x.Id, n, v)
to each pair, creating a Flattened
object from each pair.
CodePudding user response:
You can use Linq for this, a combination of SelectMany
and Zip
should do the trick
(n, v) => (n, v)
creates a tuple of pairs ofNumber
andValue
List<Compact> ls = new List<Compact>
{
new Compact(1, new int[] { 1, 2, 3 }, new double[] { 0.05, 0.02, 0.03 }),
new Compact(2, new int[] { 1, 2, 3 }, new double[] { 0.07, 0.01, 0.04 }),
new Compact(3, new int[] { 1, 2, 3 }, new double[] { 0.02, 0.025, 0.05 })
};
var flattened = ls
.SelectMany(
c => c.Number.Zip(c.Value, (n, v) => (n, v)),
(c, nv) => new Flattened(c.Id, nv.n, nv.v)
).ToList();