【问题标题】:Linq to Dictionary<string, List<string>> with Null valuesLinq to Dictionary<string, List<string>> 与 Null 值
【发布时间】:2019-11-27 10:33:40
【问题描述】:

我确实有一个Culture 列表和一个翻译列表:

public class Translation
{
    public string key { get; set; }
    public string value { get; set; }
    public string cultureId { get; set; }
}

public async Task<IActionResult> ReactGetResources(string module = "shared")
{
    string[] Languages = { "en-US", "fr-FR", "it-IT", "es-ES" };

    List<Translation> Translation = new List<Translation>();
    Translation.Add(new Translation { key = "hello", value = "Hello", cultureId = "en-US" });
    Translation.Add(new Translation { key = "hello", value = "Bonjour", cultureId = "fr-FR" });
    Translation.Add(new Translation { key = "hello", value = "Buongiorno", cultureId = "it-IT" });
    Translation.Add(new Translation { key = "goodbye", value = "Good Bye", cultureId = "en-US" });
    Translation.Add(new Translation { key = "goodbye", value = "Au revoir", cultureId = "fr-FR" });
    Translation.Add(new Translation { key = "goodbye", value = "adiós", cultureId = "es-ES" });

    Dictionary<string, List<string>> query = Translation
        .OrderBy(o => o.cultureId)
        .GroupBy(o => o.key)
        .ToDictionary(g => g.Key, g => g.Select(x => x.value).ToList());

    return Json(query);
}

当前代码IActionResult返回:

{
  "hello": [
    "Hello", //en
    "Bonjour", //fr
    "Buongiorno" //it
  ],
  "goodbye": [
    "Good Bye", //en
    "Au revoir", //fr
    "Adiós", //es
  ]
}

但我希望为缺少的翻译添加 Null 值: { "en-US", "fr-FR", "it-IT", "es-ES" }

{
  "hello": [
    "Hello", //en
    "Bonjour", //en
    "Buongiorno", //it
     null //es
  ],
  "goodbye": [
    "Good Bye", //en
    "Au revoir", //fr
    null, //it
    "Adiós" //es
  ]
}

可以只用Linq吗?或者也许我应该在字典里写一个loop 并重新填充山谷?

【问题讨论】:

  • 多个翻译实例可以共享同一个key?我还以为是PK,还是和DB无关?
  • 另一方面,您可以通过使用左连接来连接两个集合来完成您想要的操作。 Google 如何使用 LINQ 进行左连接。
  • 是的,它不是 PK,要获得特定文化的特定翻译,我在 keycultureId 上搜索

标签: c# json linq dictionary asp.net-core


【解决方案1】:

你为什么会期望这一点?您实际上是在告诉它只选择valuecultureId 和您的 Languages 数组都没有被提及或使用,那么您为什么还要期望它们以某种方式发挥作用呢?

你需要类似下面的GroupBy:

.GroupBy(g => g.key, (key, items) => Languages.Select(lang => items.FirstOrDefault(i => i.cultureId == lang)?.value))

【讨论】:

  • 事实上这不是好的答案,hellogoodbye 的键没有返回
【解决方案2】:

你可以加入你的语言列表,像这样(尚未测试)

Dictionary<string, List<string>> query = Translation
    .GroupBy(o => o.key)
    .ToDictionary(g => g.Key, g => 
        Languages.Select(l => g.FirstOrDefault(x => x.cultureId == l)?.value));

解释:

我们将组映射到语言列表中。对于每种语言,如果与cultureId 匹配的元素在组中,则使用该值,或者改为使用null。

(暂时无法测试,如有错误请见谅)

【讨论】:

  • 编辑了我的答案以包含评论。不需要在 Aleks 的建议中使用 Any 或 Contains
  • 是的,这是一个很好的答案:.ToDictionary(g =&gt; g.Key, g =&gt; Languages.Select(l =&gt; g.FirstOrDefault(x =&gt; x.cultureId == l)?.value).ToList());
  • 很高兴它有效。老实说,我更赞成克里斯的回答,因为它在分组中更早地处理了问题。
【解决方案3】:

您尝试在 linq 中执行 "left join",这可以使用 JoinDefaultIfEmpty 运算符。 只要我知道这只能在声明性语法上进行:

var query = from trans in Translation
            group trans by trans.key into transGroup
            select new
            {
                transGroup.Key,
                Values = from langId in Languages
                         join trans in transGroup on langId equals trans.cultureId 
                             into joint
                         from trans in joint.DefaultIfEmpty()
                         select trans?.value
            };

var values = query.ToDictionary(x => x.Key, x => x.Values.ToList());

我同意这不是最易读的查询,也许以程序方式维护它会更简单。

【讨论】:

    【解决方案4】:

    使用下面的代码

    Dictionary<string, List<string>> query = Translation
                .OrderBy(o => o.cultureId)
                .GroupBy(o => o.key)
                .ToDictionary(g => g.Key, g => Languages.GroupJoin(g.Select(x => x), f => f, s => s.cultureId, (f, s) => s).SelectMany(x => x.DefaultIfEmpty(),(x, y) => y != null? y.value :null).ToList());
    

    并更正最后的翻译

    Translation.Add(new Translation { key = "goodbye", value = "adiós", cultureId = "es-ES" });

    Translation.Add(new Translation { key = "goodbye", value = "adiós",cultureId = "es-US" });

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-01-25
      • 2013-08-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多