CONVERTER PARA LINQ LAMBDA

GANDA.NICK 02/12/2016 14:31:30
#469372
Olá,

Tenho uma List<[txt-color=#0000f0]Serie[/txt-color]>, a classe [txt-color=#0000f0]Serie [/txt-color]tem as seguintes propriedades:

[txt-color=#8A2BE2]PointF[][/txt-color] ChartPoints
List<[txt-color=#8A2BE2]decimal[/txt-color]> Values

Tenho uma struct chamada [txt-color=#0000f0]NearPoint [/txt-color]que é a seguite:
public struct NearPoint
{
public PointF Point { get; set; }
public int PointIndex { get; set; }
public bool IsLast { get; set; }
public decimal Value { get; set; }
public int SerieIndex { get; set; }
}



Fiz este codigo numa outra classe que funciona bem:
            int iSerie = 0;
foreach (var serie in _chartBase.Series)
{
for (int i = 0; i < serie.ChartPoints.Length; i++)
{
if (xMouseWithOffSet <= serie.ChartPoints[i].X)
{
seriesNearPoints.Add(new NearPoint()
{
Point = serie.ChartPoints[i],
PointIndex = i,
IsLast = serie.ChartPoints[i].X == serie.ChartPoints.Last().X ? true : false,
Value = serie.Values[i],
SerieIndex = iSerie
});
break;
}
}
iSerie++;
}



Tentei [Ô]converter[Ô] para lambda, mas o mais próximo que consigo fazer é isto:
            seriesNearPoints = this._chartBase.Series[1].ChartPoints
.Select((point, index) => new NearPoint()
{
Point = point,
PointIndex = index,
IsLast = point.X == _chartBase.Series[1].ChartPoints.Last().X ? true : false,
Value = _chartBase.Series[1].Values[index],
SerieIndex = 1
})
.SkipWhile(np => np.Point.X <= xMouseWithOffSet)
.Take(1)
.ToList();


Onde seriesNearPoints é:
var seriesNearPoints = new List<NearPoint>();


O Problema é que assim só funciona um elemento da List<[txt-color=#0000f0]Serie[/txt-color]>, no exemplo, o segundo elemento [1]

Queria saber se é possível fazer isto sem rodear este código com um for/foreach, o que iria mesmo assim ter problemas porque já estou a converter .ToList() no final.

Possivelmente até vou usar como tenho... mas gostava de saber como fazer..

Obrigado desde já!
KERPLUNK 02/12/2016 22:39:44
#469382
Para entendermos melhor, seria muito melhor uma explicação do que você quer fazer ao invés de código. Desse List<Serie> o que você quer fazer?
GANDA.NICK 07/12/2016 14:22:40
#469479
Obrigado por postar..

O que eu quero é tentar substituir o codigo em baixo por lambda...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var s1 = new Serie();
s1.ChartPoints = new int[] { 2, 4, 6, 8, 10 }; // são sempre ordenados
s1.Values = new List<decimal>() { 15, 20, 10, 30, 25 };

var s2 = new Serie();
s2.ChartPoints = new int[] { 2, 4, 6, 7 }; // são sempre ordenados
s2.Values = new List<decimal>() { 5, 12, 17, 13 };

var series = new List<Serie>() { s1, s2 };

Console.WriteLine([Ô]Introduza um numero entre 1 e 10[Ô]);
int input = int.Parse(Console.ReadLine());

var seriesNearPoints = new List<NearPoint>();

// Quero tentar usar Lambda neste bloco
int iSerie = 0;
foreach (var serie in series)
{
for (int i = 0; i < serie.ChartPoints.Length; i++)
{
if (input <= serie.ChartPoints[i])
{
seriesNearPoints.Add(new NearPoint()
{
Point = serie.ChartPoints[i],
PointIndex = i,
IsLast = serie.ChartPoints[i] == serie.ChartPoints.Last() ? true : false,
Value = serie.Values[i],
SerieIndex = iSerie
});
break;
}
}
iSerie++;
}
// fim do lambda

foreach (var item in seriesNearPoints)
{
Console.WriteLine();
Console.WriteLine([Ô]Point: [Ô] + item.Point );
Console.WriteLine([Ô]Point index: [Ô] + item.PointIndex);
Console.WriteLine([Ô]Is Last: [Ô] + item.IsLast);
Console.WriteLine([Ô]Value: [Ô] + item.Value);
Console.WriteLine([Ô]Serie index: [Ô] + item.SerieIndex);
}
Console.ReadKey();
}
}

public class Serie
{
public int[] ChartPoints { get; set; }
public List<decimal> Values { get; set; }
}

public struct NearPoint
{
public int Point { get; set; }
public int PointIndex { get; set; }
public bool IsLast { get; set; }
public decimal Value { get; set; }
public int SerieIndex { get; set; }
}
}


Quero procurar no array ChartPoints da classe Serie que está dentro da List<Serie> series pelo valor igual ou inferior do input e retornar:
Point ( valor que está no ChartPoints )
PointIndex ( o index do valor que está no ChartPoints )
IsLast ( se é o ultimo elemento do ChartPoints )
Value ( ChartPoints e Values da classe Serie tem sempre o mesmo numero de elemento, por isso quero o valor da List<decimal> Values correspondente ao PointIndex)
SerieIndex (o index da List<Serie> series onde se encontra este ponto)


Com o input = 9 retorna:
Point: 10
PointIndex: 4
IsLast: true
Value: 25
SerieIndex: 0

Com input = 7 retorna:
Point: 8
PointIndex: 3
IsLast: false
Value: 30
SerieIndex: 0

Point: 7
PointIndex: 3
IsLast: true
Value: 13
SerieIndex: 1


Eu estou a retornar os valores que quero.. mas gostava de saber como posso chegar aos mesmos resultado usando lambda
Obrigado.
OCELOT 07/12/2016 16:29:19
#469487
Resposta escolhida
Neste caso não vejo motivo para usar lambda já que ela torna mais difícil entender o que acontece, mas testei aqui e cheguei neste código

var pontos = series.SelectMany((s, idxS) => s.ChartPoints.Where(p => input <= p).Select((p, idxP) => new NearPoint
{
Point = p,
PointIndex = idxP,
IsLast = s.ChartPoints[idxP] == s.ChartPoints.Last(),
Value = s.Values[idxP],
SerieIndex = idxS
}).Take(1));


Como serie é um array e precisa pegar valores dentro de outro array dentro de cada elemento deste primeiro é necessário usar o SelectMany para poder pegar os valores de uma lista que está dentro de outra lista e nivelar o resultado para uma lista só.
KERPLUNK 07/12/2016 20:38:12
#469494
Acho que você não entendeu. Abstenha código. O que você quer fazer com os dados?
Tópico encerrado , respostas não são mais permitidas