You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用LINQ GroupBy对Source与Destination互逆的对象分组?

Grouping Objects with Reverse Source/Destination Pairs Using LINQ GroupBy

Hey there! This is a super common problem when working with unordered pairs—luckily, the fix is straightforward once you know the trick: create a standardized, order-agnostic key for each object. Let's walk through how to do this step by step.

The Core Idea

For any pair (Source, Destination) and its reverse (Destination, Source), we need to generate the exact same grouping key. The easiest way to do this is to sort the two values (Source and Destination) into a fixed order (e.g., alphabetical for strings, ascending for numbers) and use that sorted pair as the key.

Step-by-Step Implementation

1. Define Your Object Class (if you haven't already)

First, let's assume your objects look like this:

public class Route
{
    public string Source { get; set; }
    public string Destination { get; set; }
}

(I renamed it to Route for clarity, but you can keep your original Obj1/Obj2 naming.)

2. Basic GroupBy with Anonymous Type

Here's the simplest way to group your objects using an anonymous type as the key:

var routes = new List<Route>
{
    new Route { Source = "A", Destination = "B" },
    new Route { Source = "B", Destination = "A" },
    new Route { Source = "C", Destination = "D" },
    new Route { Source = "D", Destination = "C" },
    new Route { Source = "A", Destination = "C" }
};

var groupedRoutes = routes.GroupBy(route => 
{
    // Sort Source and Destination into a fixed order
    var first = string.Compare(route.Source, route.Destination) <= 0 ? route.Source : route.Destination;
    var second = string.Compare(route.Source, route.Destination) <= 0 ? route.Destination : route.Source;
    return new { First = first, Second = second };
});

This will group (A,B) and (B,A) into the same group, (C,D) and (D,C) into another, and (A,C) will be in its own group.

3. Simplified Syntax with ValueTuples (C# 7.0+)

If you're using a newer C# version, ValueTuples make this even cleaner:

var groupedRoutes = routes.GroupBy(route => 
    string.Compare(route.Source, route.Destination) <= 0 
        ? (route.Source, route.Destination) 
        : (route.Destination, route.Source));

The result is identical to the anonymous type approach, but the code is more concise.

4. Handling Non-String Types

If your Source and Destination are not strings (e.g., integers, enums, or custom types), use Comparer<T>.Default.Compare instead of string.Compare:

// Example for integer Source/Destination
var groupedRoutes = routes.GroupBy(route => 
{
    var compareResult = Comparer<int>.Default.Compare(route.Source, route.Destination);
    return compareResult <= 0 ? (route.Source, route.Destination) : (route.Destination, route.Source);
});

5. Reusable Extension Method

If you need to do this grouping in multiple places, create a reusable extension method:

public static class GroupingExtensions
{
    public static IEnumerable<IGrouping<(T, T), TObj>> GroupByUnorderedPair<TObj, T>(
        this IEnumerable<TObj> source,
        Func<TObj, T> getFirstValue,
        Func<TObj, T> getSecondValue)
        where T : IComparable<T>
    {
        return source.GroupBy(obj => 
        {
            var first = getFirstValue(obj);
            var second = getSecondValue(obj);
            return Comparer<T>.Default.Compare(first, second) <= 0 
                ? (first, second) 
                : (second, first);
        });
    }
}

Then call it like this:

var groupedRoutes = routes.GroupByUnorderedPair(r => r.Source, r => r.Destination);

Verifying the Result

To check the groups, you can iterate over them:

foreach (var group in groupedRoutes)
{
    Console.WriteLine($"Group: {group.Key.Item1} ↔ {group.Key.Item2}");
    foreach (var route in group)
    {
        Console.WriteLine($"  Route: {route.Source} → {route.Destination}");
    }
}

This will output:

Group: A ↔ B
  Route: A → B
  Route: B → A
Group: C ↔ D
  Route: C → D
  Route: D → C
Group: A ↔ C
  Route: A → C

内容的提问来源于stack exchange,提问作者Vincent P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:01:31