2016-02-12 91 views
1

我有2個列表。首先是包含一系列對象的主列表,每個對象都有時間戳(Datetime),類型(int),值(double)和標誌(int)。第二個列表有類型(int)和描述(字符串)。使用linq通過第二個列表修改列表

我的問題是我需要的第一個列表有各類在每個時間戳。在沒有這種對象匹配(時間戳,類型)的情況下,我需要插入一個新的對象(時間戳,類型,空值和空標誌)。

如何做到這一點使用LINQ?

實施例的對象:

var date = DateTime.UtcNow; 
var points = new List<Point> { 
    new Point { ts_utc = date   , type = 300, value = 25  , flags = 0 }, 
    new Point { ts_utc = date   , type = 400, value = 250 , flags = 0 }, 
    new Point { ts_utc = date   , type = 500, value = 2500 , flags = 0 }, 
    new Point { ts_utc = date.AddDays(1) , type = 300, value = 26  , flags = 0 }, 
    //new Point { ts_utc = date.AddDays(1) , type = 400, value = 260, flags = 0 }, 
    new Point { ts_utc = date.AddDays(1) , type = 500, value = 2600 , flags = 0 }, 
    new Point { ts_utc = date.AddDays(2) , type = 300, value = 27  , flags = 0 }, 
    new Point { ts_utc = date.AddDays(2) , type = 400, value = 270 , flags = 0 }, 
    new Point { ts_utc = date.AddDays(2) , type = 500, value = 2700 , flags = 0 } 
}; 
var desc = new List<Description> { 
    new Description{ type = 300, description = "300" }, 
    new Description{ type = 400, description = "400" }, 
    new Description{ type = 500, description = "500" }, 
}; 

var q = from p in points 
     join d in desc on p.type equals d.type into joined 
     from subd in joined.DefaultIfEmpty(...) 
     ... 

查詢是不完整的。在上面的列表中,我已將一個Point作爲缺省值(時間戳,類型)組合的示例進行了評論。在那個地方,我想有一個默認對象插入時間戳從一個現有的類型,但插入缺少的類型。值和標誌應該爲空。我想一個小組可能會派上用場?

回答

1

如果我理解正確的話,你要設定的時間戳和類型組合不基於具有的時間印記一個條目集第一個集合中存在,但不是第二集合中的所有類型。

var missing = points.GroupBy(p => p.ts_utc) 
        .SelectMany(g => desc.Where(d => g.All(p => p.type != d.type)) 
              .Select(d => new 
                 { 
                  ts = g.Key, 
                  type = d.type 
                 })); 

這將第一組由該時間標記然後點爲每個分組將從描述列表進行過濾,具有所存在的組中,僅留下描述與沒有按」一個類型的類型的任何描述這個時間戳存在。然後它從組密鑰和「缺少」類型中選擇時間戳。最後SelectMany會使結果變平。

然後,您可以遍歷結果,並添加條目到points集合。

foreach(var m in missing) 
    points.Add(new Point { ts_utc = m.ts, type = m.type }); 
1

糾正我,如果我錯了,但你要「填補空白」列表1 - 使得它包含與每一個現有的類型,爲每個現有的日期項?

如果是的話,我只想得到所有不同的項目遍歷並創建一個嵌套的foreach循環...

List<DateTime> allExistingDates = points.Select(o => o.ts_utc).Distinct().ToList(); 
List<int> allExistingTypes = points.Select(o => o.type).Concat(desc.Select(o => o.type)).Distinct().ToList(); 

foreach (DateTime d in allExistingDates) 
    foreach (int t in allExistingTypes) 
     if (points.Any(o => o.ts_utc == d && o.type == t) == false) 
      points.Add(new Point { ts_utc = d, type = t}); 
0

我發現這是解決我的名單,而不必訴諸於多個查詢:

var w = from p in points 
     group p by p.ts_utc into g 
     from d in desc 
     select points.Where(r => r.ts_utc == g.Key && r.type == d.type).DefaultIfEmpty(new Point 
     { 
      ts_utc = g.Key, 
      type = d.type 
     }).FirstOrDefault(); 

我認爲它沒有得到任何比這更短。兩者(目前)的其他答案都幫助我達成了這個解決方案。它不會創建不必要的新點,是1個linq查詢,並且我認爲(使用1個linq查詢)它不會更高效。

+0

這也將「刪除」基於時間戳和類型重複。 – juharr

+0

是的。幸運的是,我可以確信重複不會發生。 – galmok