使用 C# 在复杂的 JSON 数组中查找和打印重复项

Posted

技术标签:

【中文标题】使用 C# 在复杂的 JSON 数组中查找和打印重复项【英文标题】:Find and print duplicates in a complex JSON array using C# 【发布时间】:2021-04-29 13:13:15 【问题描述】:

我正在尝试使用 .NET 中的 C# 从复杂的嵌套 JSON 数组中找出并打印重复项。

我想检查值 "title" 是否重复,并且还有一个嵌套的 JSON 数组 (items) 具有以下值:title 和 value 我要检查其中的重复项。

因此,嵌套数组的 titlevalue 值应与其他嵌套数组值的值进行比较。 外部的“标题”应与外部的检查。

id 和 sourceId 应该被忽略

尝试使用 foreach 执行此操作,但无法使用 . (点)。 然后尝试使用 for 循环,但我迷路了。

作为结果,我想打印重复的值。

你能帮帮我吗?

JSON 数组的外观概览如下


    "id": "0789a960-45de-11ea-ae56-23ecd3bd0e35",
    "sourceId": "6e009cc0-fc83-11e9-8fb9-01af70ec8d3f",
    "title": "Glass-reinforced concrete (GRC) built-in quoins",
    "items": [
        "title": "Description",
        "value": ""
    , 
        "title": "Manufacturer",
        "value": ""
    , 
        "title": "Height (overall)",
        "value": ""
    , 
        "title": "Applied surface finish",
        "value": ""
    , 
        "title": "Applied finish colour",
        "value": ""
    ]
, 
    "id": "0a607010-45de-11ea-ae56-23ecd3bd0e35",
    "sourceId": "73a96f31-fc83-11e9-8fb9-01af70ec8d3f",
    "title": "Clay bricks",
    "items": [
        "title": "Description",
        "value": ""
    , 
        "title": "Manufacturer",
        "value": ""
    , 
        "title": "Standard",
        "value": ""
    , 
        "title": "Brick description",
        "value": ""
    , 
        "title": "Execution",
        "value": ""
    ]
, 
    "id": "0ce40db0-45de-11ea-ae56-23ecd3bd0e35",
    "sourceId": "73a96f31-fc83-11e9-8fb9-01af70ec8d3f",
    "title": "Clay bricks",
    "items": [
        "title": "Description",
        "value": ""
    , 
        "title": "Manufacturer",
        "value": ""
    , 
        "title": "Standard",
        "value": ""
    , 
        "title": "Appearance",
        "value": ""
    , 
        "title": "Execution",
        "value": ""
    ]
,  ............. and so on

【问题讨论】:

您没有发布有效的 JSON,这些项目是否在数组中? 另外,你期待什么输出?以上3项根据你的描述都是不一样的吧? @DavidG 这是一个复杂 JSON 数组的示例,只是为了说明它的外观。如果有重复的值,我想打印它们。 @DavidG 如果它有助于类似的事情可能是这个i.stack.imgur.com/JXV19.png 你在哪里解决问题? 【参考方案1】:

一种方法是将上述 JSON 转换为 C# 对象以保存您要反序列化的属性,例如:

public class Thing

    public string Title  get; set; 
    public List<TitleValue> Items  get; set; 


public class TitleValue

    public string Title  get; set; 
    public string Value  get; set; 

    // This is needed later for the comparer
    public override int GetHashCode()
    
        unchecked
        
            int hash = 17;
            hash = hash * 31 + Title.GetHashCode();
            hash = hash * 31 + Value.GetHashCode();
            return hash;
        
    

现在你可以反序列化成这样的项目列表:

// If you are using Newtonsoft JSON.Net:
var things = JsonConvert.DeserializeObject<List<Thing>>(jsonString);

// If you are using System.Text.Json:

var settings = new System.Text.Json.JsonSerializerOptions

    PropertyNameCaseInsensitive = true
;

var things = JsonSerializer.Deserialize<List<Thing>>(jsonString, settings);

接下来您可以创建一个实现IEqualityComparer&lt;Thing&gt; 的类,您可以将其传递给Linq GroupBy。例如:

public class ThingEqualityComparer : IEqualityComparer<Thing>

    public bool Equals(Thing x, Thing y)
    
        if (!x.Title.Equals(y.Title))
            return false;

        if (x.Items.Count() != y.Items.Count())
            return false;

        foreach (var item in x.Items)
        
            if (!y.Items.Any(otherItem => otherItem.Title.Equals(item.Title) && 
                                          otherItem.Value.Equals(item.Value)))
                return false;
        

        return true;
    

    public int GetHashCode(Thing obj)
    
        unchecked
        
            int hash = 17;
            hash = hash * 31 + obj.Title.GetHashCode();
            foreach (var item in obj.Items)
            
                hash = hash * 31 + item.GetHashCode();
            
            return hash;
        
    

现在您可以运行一些 Linq 查询,例如:

var thingCounts = things
    .GroupBy(t => t, new ThingEqualityComparer())
    .Select(g => new 
    
        Thing = g.Key, 
        Count = g.Count() 
    );

如果您想在该列表中查找重复项,您可以使用 Where 子句过滤它们:

var duplicateThingCounts = thingCounts.Where(tc => tc.Count > 1)

现在您可以对重复项做任何您想做的事情,例如打印出您喜欢的任何内容:

foreach (var thingCount in duplicateThingCounts)

    Console.WriteLine(thingCount.Thing.Title);

【讨论】:

你能检查一下这个有在线编辑器的链接吗? dotnetfiddle.net/sln3wH 你想让我用那个链接做什么? 是在线编辑器.net fiddle,我试图解决我在这篇文章中描述的问题。通过阅读可能会更好地理解我的观点。

以上是关于使用 C# 在复杂的 JSON 数组中查找和打印重复项的主要内容,如果未能解决你的问题,请参考以下文章

使用 C# 的复杂 JSON 对象序列化

在 C# 中绘制和打印复杂文档(改进/替换我的 PrintDocument)

C#:在结构数组中查找和更改元素

如何用O(nlogn)或O(n)的时间复杂度在python中解决对和问题?

使用 LINQ 在 C# 中查找数字数组的累积和

在 C# 中打印数组的所有内容