Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/amazon-s3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 遍历列表以使用.NET添加元素_C#_Linq_List_Linq To Objects - Fatal编程技术网

C# 遍历列表以使用.NET添加元素

C# 遍历列表以使用.NET添加元素,c#,linq,list,linq-to-objects,C#,Linq,List,Linq To Objects,我有一个物品清单。每个对象都有一个整数和一个DateTime变量,该变量包含月份和年份值。我希望遍历列表并通过添加缺少的月份(数量为0)来填充列表,以便在列表中表示所有连续月份。实现这一目标的最佳方式是什么 例如: 原始列表 {Jan10,3},{Feb10,4},{Apr10,2},{May10,2},{Aug10,3},{Sep10,-3},{Oct10,6},{Nov10,3},{Dec10,7},{Feb11,3} var months = new [] { "Jan", "Feb",

我有一个物品清单。每个对象都有一个整数和一个DateTime变量,该变量包含月份和年份值。我希望遍历列表并通过添加缺少的月份(数量为0)来填充列表,以便在列表中表示所有连续月份。实现这一目标的最佳方式是什么

例如: 原始列表

{Jan10,3},{Feb10,4},{Apr10,2},{May10,2},{Aug10,3},{Sep10,-3},{Oct10,6},{Nov10,3},{Dec10,7},{Feb11,3}

var months = new [] { "Jan", "Feb", "Mar", ... };
var yourList = ...;
var result = months.Select(x => {
  var yourEntry = yourList.SingleOrDefault(y => y.Month = x);
  if (yourEntry != null) {
    return yourEntry;
  } else {
    return new ...;
  }
});
新名单


{Jan10,3},{Feb10,4},{Mar10,0},{Apr10,2},{May10,2},{Jun10,0},{Jul10,0},{Aug10,3},{Sep10,-3},{Oct10,6},{Nov10,3},{Dec10,7},{Jan11,0},{Feb11,3},{p>一个可能的算法是跟踪前几个月和当前几个月。如果“上一个”和“当前”之间的差值为1个月,请将“当前”附加到结果。如果差异超过一个月,请先添加缺少的月份,然后复制当前月份

var months = new [] { "Jan", "Feb", "Mar", ... };
var yourList = ...;
var result = months.Select(x => {
  var yourEntry = yourList.SingleOrDefault(y => y.Month = x);
  if (yourEntry != null) {
    return yourEntry;
  } else {
    return new ...;
  }
});
Foo prev = months.First();
List<Foo> result = new List<Foo> { prev };
foreach (Foo foo in months.Skip(1))
{
    DateTime month = prev.Month;
    while (true)
    {
        month = month.AddMonths(1);
        if (month >= foo.Month)
        {
            break;
        }
        result.Add(new Foo { Month = month, Count = 0 });
    }
    result.Add(foo);
    prev = foo;
}
编译此文件所需的其他代码:

class Foo
{
    public DateTime Month { get; set; }
    public int Count { get; set; }
}

List<Foo> months = new List<Foo>
{
    new Foo{ Month = new DateTime(2010, 1, 1), Count = 3 },
    new Foo{ Month = new DateTime(2010, 2, 1), Count = 4 },
    new Foo{ Month = new DateTime(2010, 4, 1), Count = 2 },
    new Foo{ Month = new DateTime(2010, 5, 1), Count = 2 },
    new Foo{ Month = new DateTime(2010, 8, 1), Count = 3 },
    new Foo{ Month = new DateTime(2010, 9, 1), Count = -3 },
    new Foo{ Month = new DateTime(2010, 10, 1), Count = 6 },
    new Foo{ Month = new DateTime(2010, 11, 1), Count = 3 },
    new Foo{ Month = new DateTime(2010, 12, 1), Count = 7 },
    new Foo{ Month = new DateTime(2011, 2, 1), Count = 3 }
};
class-Foo
{
公共日期时间月{get;set;}
公共整数计数{get;set;}
}
列表月份=新列表
{
新Foo{Month=newdatetime(2010,1,1),Count=3},
新Foo{Month=newdatetime(2010,2,1),Count=4},
新Foo{Month=newdatetime(2010,4,1),Count=2},
新Foo{Month=newdatetime(2010,5,1),Count=2},
新Foo{Month=newdatetime(2010,8,1),Count=3},
新Foo{Month=newdatetime(2010,9,1),Count=-3},
新Foo{Month=newdatetime(2010,10,1),Count=6},
新Foo{Month=newdatetime(2010,11,1),Count=3},
新Foo{Month=newdatetime(2010,12,1),Count=7},
新Foo{Month=newdatetime(2011,2,1),Count=3}
};

注意:为简单起见,我没有处理原始列表为空的情况,但您应该在生产代码中执行此操作。

让我们假设该结构作为
列表保存

var oldList = GetTheStartList();
var map = oldList.ToDictionary(x => x.Item1.Month);

// Create an entry with 0 for every month 1-12 in this year 
// and reduce it to just the months which don't already 
// exist 
var missing = 
  Enumerable.Range(1,12)
  .Where(x => !map.ContainsKey(x))
  .Select(x => Tuple.Create(new DateTime(2010, x,0),0))

// Combine the missing list with the original list, sort by
// month 
var all = 
  oldList
  .Concat(missing)
  .OrderBy(x => x.Item1.Month)
  .ToList();

一种方法是实现对象的IEqualityComparer,然后可以创建一个“填充”对象列表,使用“Except”扩展方法添加到现有列表中。有点像下面

public class MyClass
{
    public DateTime MonthYear { get; set; }
    public int Quantity { get; set; }
}

public class MyClassEqualityComparer : IEqualityComparer<MyClass>
{
    #region IEqualityComparer<MyClass> Members

    public bool Equals(MyClass x, MyClass y)
    {
        return x.MonthYear == y.MonthYear;
    }

    public int GetHashCode(MyClass obj)
    {
        return obj.MonthYear.GetHashCode();
    }

    #endregion
}
公共类MyClass
{
public DateTime MonthYear{get;set;}
公共整数数量{get;set;}
}
公共类MyClassEqualityComparer:IEqualityComparer
{
#地区资格比较成员
公共布尔等于(MyClass x,MyClass y)
{
返回x.MonthYear==y.MonthYear;
}
公共int GetHashCode(MyClass obj)
{
返回obj.MonthYear.GetHashCode();
}
#端区
}
然后你可以这样做

// let this be your real list of objects    
List<MyClass> myClasses = new List<MyClass>() 
{
    new MyClass () { MonthYear = new DateTime (2010,1,1), Quantity = 3},
    new MyClass() { MonthYear = new DateTime (2010,12,1), Quantity = 2}
};

List<MyClass> fillerClasses = new List<MyClass>();
for (int i = 1; i < 12; i++)
{
    MyClass filler = new MyClass() { Quantity = 0, MonthYear = new DateTime(2010, i, 1) };
    fillerClasses.Add(filler);
}

myClasses.AddRange(fillerClasses.Except(myClasses, new MyClassEqualityComparer()));
//这是您真正的对象列表
List myClasses=新列表()
{
new MyClass(){MonthYear=new DateTime(2010,1,1),Quantity=3},
new MyClass(){MonthYear=new DateTime(2010,12,1),Quantity=2}
};
List fillerClasses=新列表();
对于(int i=1;i<12;i++)
{
MyClass filler=new MyClass(){Quantity=0,MonthYear=new DateTime(2010,i,1)};
填充类。添加(填充);
}
AddRange(fillerClasses.Exception(myClasses,new MyClassEqualityComparer());

如果我正确理解“日期时间”月份:

for(int i=0;i<12;i++)
如果(!original.Any(n=>n.datetimeproperty.Month==i))
Add(newmyclass{DateTimePropery=newdatetime(2010,i,1),IntQuantity=0});
var sorted=original.OrderBy(n=>n.datetimeproperty.Month);

考虑到年限、速度和可扩展性,它可以作为可枚举的扩展(甚至可能使用通用属性选择器)。 如果日期已经被截断到月份,并且列表在执行FILSET之前被命令,请考虑此方法:

public static class Extensions
{
    public static IEnumerable<Tuple<DateTime, int>> FillMissing(this IEnumerable<Tuple<DateTime, int>> list)
    {
        if(list.Count() == 0)
            yield break;
        DateTime lastDate = list.First().Item1;
        foreach(var tuple in list)
        {
            lastDate = lastDate.AddMonths(1);
            while(lastDate < tuple.Item1)
            {
                yield return new Tuple<DateTime, int>(lastDate, 0);
                lastDate = lastDate.AddMonths(1);
            }
            yield return tuple;
            lastDate = tuple.Item1;
        }
    }
}

如何获得包含月份和年份的DateTime变量?该类有一个Date类型的字段/属性,该字段/属性管理不保存日期?或者,它是一个字符串(“Apr10”)字段/属性吗?这个列表应该是一天吗?@Addie如果您使用
2010年1月
而不是
2010年1月10日
,您的示例可能会更清楚,看起来有一群人认为这意味着
1月10日
,尽管您在文本中指定了月份和年份,但此列表是动态的。DateTime对象唯一重要的部分是月份和年份。该列表通常包括多个年份,如1月10日、2月10日、1月11日等。我之前也按日期对列表进行了排序@Patrick DateTime对象将保存月份和年份以外的值,但我不关心它们,也不会访问这些值。我在Apr10中编写了一个伪代码,表示只有月份和年份的DateTime对象significant@JaredPar我不明白你的问题。你能澄清一下吗?列表是月/年DateTime对象以及一个表示数量的整数值的集合。他在同一个列表中有Jan10和Jan11。@Tanzelax,这看起来像一个打字错误,我将添加一条注释以确认Nah,他希望最终列表中有14个元素,从2010年1月到2011年2月,几乎每个发布回复的人都在他的例子中忽略了这一点p@Tanzelax. 正确,我特别需要考虑多年。哦,与我的解决方案类似:)这适用于规范,非常简单,性能也很好。实际上,即使它适用于规范,也不需要创建新的对象列表,因为您可以使用yield指令遍历有序列表并只返回新的缺少的对象(详情如下)
public static class Extensions
{
    public static IEnumerable<Tuple<DateTime, int>> FillMissing(this IEnumerable<Tuple<DateTime, int>> list)
    {
        if(list.Count() == 0)
            yield break;
        DateTime lastDate = list.First().Item1;
        foreach(var tuple in list)
        {
            lastDate = lastDate.AddMonths(1);
            while(lastDate < tuple.Item1)
            {
                yield return new Tuple<DateTime, int>(lastDate, 0);
                lastDate = lastDate.AddMonths(1);
            }
            yield return tuple;
            lastDate = tuple.Item1;
        }
    }
}
    private List<Tuple<DateTime, int>> items = new List<Tuple<DateTime, int>>()
    {
        new Tuple<DateTime, int>(new DateTime(2010, 1, 1), 3),
        new Tuple<DateTime, int>(new DateTime(2010, 2, 1), 4),
        new Tuple<DateTime, int>(new DateTime(2010, 4, 1), 2),
        new Tuple<DateTime, int>(new DateTime(2010, 5, 1), 2),
        new Tuple<DateTime, int>(new DateTime(2010, 8, 1), 3),
        new Tuple<DateTime, int>(new DateTime(2010, 9, 1), -3),
        new Tuple<DateTime, int>(new DateTime(2010, 10, 1), 6),
        new Tuple<DateTime, int>(new DateTime(2010, 11, 1), 3),
        new Tuple<DateTime, int>(new DateTime(2010, 12, 1), 7),
        new Tuple<DateTime, int>(new DateTime(2011, 2, 1), 3)
    };

    public Form1()
    {
        InitializeComponent();
        var list = items.FillMissing();
        foreach(var element in list)
        {
            textBox1.Text += Environment.NewLine + element.Item1.ToString() + " - " + element.Item2.ToString();
        }
    }
2010-01-01 00:00:00 - 3
2010-02-01 00:00:00 - 4
2010-03-01 00:00:00 - 0
2010-04-01 00:00:00 - 2
2010-05-01 00:00:00 - 2
2010-06-01 00:00:00 - 0
2010-07-01 00:00:00 - 0
2010-08-01 00:00:00 - 3
2010-09-01 00:00:00 - -3
2010-10-01 00:00:00 - 6
2010-11-01 00:00:00 - 3
2010-12-01 00:00:00 - 7
2011-01-01 00:00:00 - 0
2011-02-01 00:00:00 - 3