如何填写列表中属性值的间隙?

时间:2017-12-12 14:42:44

标签: c# linq

我有一个清单:

List<BtnCountViews> btnCountViewsList;

BtnCountViews类如下所示:

public class BtnCountViews
{
    public int DayOfYear { get; set; }
    public int BtnCount { get; set; }
    public int Views { get; set; }
}

我有一个相当不寻常的要求,我不知道如何开始实施它。

我想做的是使用BtnCount为0且视图为0的对象为缺少的DayOfYear填充btnCountViewsList和`BtnCountViews。

为了给我一个开始,任何人都可以告诉我如何在btnCountViewsList中找到最小和最大DayOfYear。注意我用LINQ标记了这个,但我不确定这是否是最好的工具。

如果有人可以提出填补遗失物品的方法但也不会真的成为这个问题的焦点,我也很高兴,因为我认为我需要找出如何获得最小值和最大值。

7 个答案:

答案 0 :(得分:1)

这适用于linqpad:

Int32 max = 0, min = 0;
btnCountViewsList.ForEach(x => {
     min = Math.Min(x.Views, min);
     max = Math.Max(x.Views, max);
});

答案 1 :(得分:1)

您可以在未明确查找minmax的情况下添加缺失的日期:

  • DayOfYear升序排序(how?
  • 在列表末尾开始一个循环索引i,然后向后工作; i达到零时停止
  • 比较DayOfYeari
  • i-1属性
  • 如果两天相差一个,请下移到下一个i
  • 否则,请将DayOfYear设置为btnCountViewsList[i]减去1的新记录。

在此过程结束时,您的列表将包含DayOfYear的每个值的条目。以下是一个示例实现:

items.Sort((x, y) => x.DayOfYear.CompareTo(y.DayOfYear));
Console.WriteLine("Before: {0}", string.Join(", ", items.Select(x => x.DayOfYear)));
int i = items.Count-1;
while (i > 0) {
    if (items[i].DayOfYear == items[i-1].DayOfYear+1) {
        i--;
    } else {
        items.Insert(i, new BtnCountViews { DayOfYear = items[i].DayOfYear-1 });
    }
}

Demo.

答案 2 :(得分:1)

  

我想要做的是使用`BtnCountViews为缺少的DayOfYear填充btnCountViewsList,其中包含BtnCount为0且Views为0的对象。

我的建议是,我们不会试图找到失踪的日子,我们创造所有:

BtnCountViews[] arr = new BtnCountViews[365]; // or 366?

// suppose DayOfYear begins with 0.
for (int i = 0; i < arr.Length; i++)
{
    arr[i] = new BtnCountViews { DayOfYear = i };
}
foreach (BtnCountViews item in btnCountViewsList)
{
    arr[item.DayOfYear].BtnCount = item.BtnCount;
    arr[item.DayOfYear].Views = item.Views;
}

然后arr就是你想要的。

如果结果应该是btnCountViewsList

btnCountViewsList.Clear();
btnCountViewsList.AddRange(arr);

答案 3 :(得分:1)

所以我的懒惰说,制作一个回填列表并使用您现有的(和gappy)列表作为地图。

public static IList<BtnCountViews> GetDefaultList()
{
    var defaultList = Enumerable.Range(1, 365).Select(e =>
        new BtnCountViews
        {
            DayOfYear = e,
            BtnCount = 0,
            Views = 0
        }
    ).ToList();

    return defaultList;
}

遍历回填列表并查阅地图以查看DayOfYear值是否作为键存在,如果不存在,则将其添加到地图中。

public static IList<BtnCountViews> GetBackFilledList(IList<BtnCountViews> incoming)
{
    var map = incoming.ToDictionary(k => k.DayOfYear, v => v);
    var defaultList = GetDefaultList();

    foreach(var itm in defaultList)
    {
        if (map.ContainsKey(itm.DayOfYear)) continue;

        map.Add(itm.DayOfYear, itm);
    }

    return map.Select(m => m.Value).ToList();
}

迭代完成后,将地图转换为一个列表,该列表现在应该包含原始值+缺少DayOfYear条目的默认值。

return map.Select(m => m.Value).ToList();

此处示例程序的Dotnetfiddle:https://dotnetfiddle.net/wSJy56

有更优雅的方法吗?最肯定的是。但是这个代码在大约0.011秒内执行,对我来说这是相当不错的,只要你不反复调用这个功能(例如你决定分析30年的数据并需要在0.011秒内完成)。但是,我们必须更多地关注并行性而不是编码优雅来解决这些蠕虫。

希望这会有所帮助......

答案 4 :(得分:0)

尝试以下

btnCountViewsList = btnCountViewsList.Where(b => b.BtnCount == 0).Where(v => v.Views == 0).ToList();

如果我理解你的要求,你想得到BtnCount = 0和Views = 0的对象。

这将选择Views = 0的所有对象,然后IEnumarable将通过另一个LINQ表达式,其中它只选择等于0的其他属性。

答案 5 :(得分:0)

最短的linq方式,使用左外连接(LEFT OUTER JOIN in LINQ)和范围

 var result = (from a in Enumerable.Range(0, 365)
                         join lst in btnCountViewsList on a equals lst.DayOfYear into ps
                         from p in ps.DefaultIfEmpty()
                         select (p==null) ? new BtnCountViews() { DayOfYear = a}:p).ToList()

答案 6 :(得分:0)

在其他一些回复的行中,但没有硬编码一年中的总天数,因为闰年​​将有366天

var range = new 
{
    Start = new DateTime(2017, 1, 1),
    End = new DateTime(2017, 12, 31),
};

var days = Enumerable.Range(range.Start.DayOfYear, range.End.DayOfYear);

var query = from day in days
            from counter in 
            (
                from temp in btnCountViewsList
                where temp.DayOfYear == day
                select temp
            ).DefaultIfEmpty()
            select new BtnCountViews
            {
                DayOfYear = day,
                BtnCount = counter == null ? 0 : counter.BtnCount,
                Views = counter == null ? 0 : counter.Views,
            };

会给你类似的东西

enter image description here