J'ai une Liste et je veux additionner les mêmes valeurs
var result = new List<DataPoint>
{
new DataPoint(){Name = "Test",Value = 30},
new DataPoint(){Name = "Test1",Value = 20},
new DataPoint(){Name = "Test",Value = 11}
};
le résultat devrait être une autre liste qui ressemble à ceci (additionner tous les noms "Test", avant un autre nom)
var list = new List<DataPoint>
{
new DataPoint(){Name = "Test",Value = 10},
new DataPoint(){Name = "Test",Value = 10},
new DataPoint(){Name = "Test",Value = 10},
new DataPoint(){Name = "Test1",Value = 20},
new DataPoint(){Name = "Test",Value = 11}
};
comment puis-je faire cela?
5 Réponses :
D'abord, vous additionnez les premiers points de données aussi longtemps qu'ils portent le nom "Test". Ensuite, vous créez une nouvelle liste qui contient un nouveau point de données avec votre somme. À cela, vous ajoutez tous les éléments de votre première liste qui viennent après que vos points de données sont appelés test. Vous pouvez utiliser les méthodes LINQ TakeWhile et SkipWhile pour cela.
int sum = list.TakeWhile(x => x.Name == "Test").Sum(x => x.Value);
var firstDataPoint = new DataPoint("Test", sum);
var result = new List<DataPoint> { firstDataPoint };
result.AddRange(list.SkipWhile(x => x.Name == "Test"));
Cette solution nécessite de mélanger avec la boucle externe s'il y a plus de 2 catégories que je considérerais comme un inconvénient: /
Ceci est lié au commentaire de Knoop à la question. Malheureusement, OP n'a pas spécifié ce qui devrait se passer avec les entrées nommées "Test" qui viennent après un autre nom.
Il existe de nombreuses solutions, l'une d'elles est: (mise à jour)
var result = new List<DataPoint>();
var item = list.First();
foreach (var dataPoint in list.Skip(1))
{
if (item.Name == dataPoint.Name)
{
item.Value += dataPoint.Value;
}
else
{
result.Add(item);
item = new DataPint() { Name = dataPoint.Name, Value = dataPoint.Value };
}
}
result.Add(item);
return result.ToList();
Veuillez vérifier votre solution LINQ . Je pense que cela ne produira pas le résultat attendu pour l'échantillon d'OP.
Cela ne résultera certainement pas en une réponse correcte. Notez que les entrées avec Name = "Test" apparaissent plusieurs fois dans le jeu de résultats (le groupe avant et après l'entrée "Test1" sont des groupes différents)
Pourquoi pas une simple boucle? Quelque chose comme ceci:
result = new List<DataPoint>();
foreach (DataPoint p in list)
if (result.Count <= 0 || result[result.Count - 1].Name != p.Name)
result.Add(new DataPoint() {Name = p.Name, Value = p.Value});
else
result[result.Count - 1].Value += p.Value;
@Maximilian Ast: Merci! Je suis désolé pour la faute de frappe
Merci beaucoup! Cordialement
J'aime à quel point c'est court tout en atteignant tous les bons points ... très agréable.
Je résoudrais ce problème avec une boucle foreach classique et stockerais la valeur précédente dans la somme si le nom est eqal:
var result = new List<DataPoint>();
DataPoint sum = null;
foreach (var dp in list)
{
if(sum == null)
{
// First element, so create the sum object
sum = new DataPoint { Name = dp.Name, Value = dp.Value };
}
else if (sum.Name == dp.Name)
{
// Same as the one before, so increment the Value
sum.Value += dp.Value;
}
else
{
// Differs from the sone before, so store the sum
result.Add(sum);
// Reset the sum
sum = new DataPoint { Name = dp.Name, Value = dp.Value };
}
}
// Add the last sum to the group
result.Add(sum);
Résultat: p >
DP: {Test, 30}
DP: {Test1, 20}
DP: {Test, 11}
Name: Test, Value: 30 Name: Test1, Value: 20 Name: Test, Value: 11
L'exemple laisse donc quelques questions sur d'autres cas. Si après l'entrée «Test1», il y a plusieurs entrées «Test», doivent-elles également être additionnées ou s'agit-il simplement du premier ensemble d'entrées «Test»? Et s'il y a plusieurs entrées "Test1"?