跟踪foreach循环中的先前元素

时间:2016-11-09 17:26:18

标签: linq c#-4.0 foreach

假设我有一个小行星对象列表,如下所示:

  • 9_Amphitrite
  • 24_Themis
  • 259_Aletheia
  • 31_Euphrosyne
  • 511_Davida
  • 87_Sylvia
  • 9_Metis
  • 41_Daphne

每个小行星都有一个标题,一个 StartRoationPeriod 和一个 EndRoationPeriod

我需要根据当前小行星StartRoationPeriod和之前的小行星EndRoationPeriod与轨道常数的接近程度来连接它们的名称,然后吐出连接的标题。

因此,使用上面的列表,最终对象可能如下所示:

  • 9_Amphitrite
  • 24_Themis; 259_Aletheia
  • 31_Euphrosyne; 511_Davida; 87_Sylvia
  • 9_Metis
  • 41_Daphne

这要求我跟踪当前和以前的小行星。

我开始编写循环,但我不确定在哪里甚至如何检查当前小行星开始旋转周期与之前的小行星结束旋转周期...基本上,它只是变得凌乱快...

        string asteroid_title = string.Empty;
        Asteroid prev_asteroid = null;

        foreach (var asteroid in SolarSystem)
        {
            if (prev_asteroid != null)
            {
                 if (asteroid.StartRoationPeriod + OrbitalConstant >= prev_asteroid.EndRoationPeriod)
                 {
                      asteroid_title = asteroid_title + asteroid.Title;

                 } else {
                      asteroid_title = asteroid.Title;
                      yield return CreateTitle();
                 }
            }
            prev_evt = evt;
        }

1 个答案:

答案 0 :(得分:1)

我认为这应该对你有用(如果聚合看起来太复杂,试着将它转换为foreach,这很容易)

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

namespace Program
{
    class Asteroid
    {
        public int EndRoationPeriod { get; internal set; }
        public string Name { get; internal set; }
        public int StartRoationPeriod { get; internal set; }
    }

    class AsteroidGroup
    {
        public int EndRoationPeriod { get; internal set; }
        public string Names { get; internal set; }
    }
    internal class Program
    {
        private static void Main(string[] args)
        {
            int OrbitalConstant = 10;
            List<Asteroid> SolarSystem = new List<Asteroid>()
            {
                new Asteroid() {  Name= "9_Amphitrite" ,StartRoationPeriod=10  ,EndRoationPeriod=50},
                new Asteroid() {  Name= "24_Themis" ,StartRoationPeriod=45,EndRoationPeriod=100},
                new Asteroid() {  Name= "259_Aletheia",StartRoationPeriod=40 ,EndRoationPeriod=150},
                new Asteroid() {  Name= "31_Euphrosyne" ,StartRoationPeriod=60,EndRoationPeriod=200},
                new Asteroid() {  Name= "511_Davida" ,StartRoationPeriod=195,EndRoationPeriod=250},
                new Asteroid() {  Name= "87_Sylvia" ,StartRoationPeriod=90,EndRoationPeriod=300},
                new Asteroid() {  Name= "9_Metis" ,StartRoationPeriod=100,EndRoationPeriod=350},
                new Asteroid() {  Name= "41_Daphne" ,StartRoationPeriod=110,EndRoationPeriod=400},
            };

             var result = //I skip the first element because I initialize a new list with that element in the next step
                          SolarSystem.Skip(1)
                          //The first argument of Aggregate is a new List with your first element
                          .Aggregate(new List<AsteroidGroup>() { new AsteroidGroup { Names = SolarSystem[0].Name, EndRoationPeriod = SolarSystem[0].EndRoationPeriod } },
                          //foreach item in your list this method is called,l=your list and a=the current element     
                          //the method must return a list                                         
                          (l, a) =>
                           {
                             //Now this is your algorithm
                             //Should be easy to undrestand

                              var last = l.LastOrDefault();
                              if (a.StartRoationPeriod + OrbitalConstant >= last.EndRoationPeriod)
                              {
                                  last.Names += " " + a.Name;
                                  last.EndRoationPeriod = a.EndRoationPeriod;
                               }
                               else
                                    l.Add(new AsteroidGroup { Names = a.Name, EndRoationPeriod = a.EndRoationPeriod });

                                //Return the updated list so it can be used in the next iteration
                                return l;
                           });

更紧凑的解决方案

var result = SolarSystem
             .Skip(1)
             .Aggregate( SolarSystem.Take(1).ToList(),
                         (l, a) => (a.StartRoationPeriod + OrbitalConstant >= l[l.Count - 1].EndRoationPeriod) ?
                         (l.Take(l.Count - 1)).Concat(new List<Asteroid> { new Asteroid() { Name = l[l.Count - 1].Name += " " + a.Name, EndRoationPeriod = a.EndRoationPeriod } }).ToList() :
                          l.Concat(new List<Asteroid> { a }).ToList()
                       );
相关问题