在列表中存储整数对

发布于 2024-10-06 04:59:37 字数 541 浏览 1 评论 0 原文

如何在列表中存储整数对? 我知道我可以为它们创建一个类,例如:

class Pair  
{
    int i1,i2;
}

但是如果我这样做,我将无法使用 Contains 函数来检查给定的对是否在列表中。我怎样才能做到这一点,以便我可以轻松地将整数存储在列表中并检查一对整数是否已经存在?我无法使用表格,因为不知道会有多少对。

编辑:
忘记补充: 在我的程序中, (x, y) 和 (y, x) 对被视为平等。

编辑:
检查 Point 是否在列表中时,(x,y) 和 (y,x) 相等,但 xy 不能相等交换是因为 xy 表示两点之间的连接(整数是点的 id,不,我不能使用任何引用等...)。当我检查 List 是否包含连接时,它是 (x,y) 还是 (y,x) 并不重要,但稍后我会需要该信息。

How can I store pairs of integers in a List?
I know I could make a class for them like:

class Pair  
{
    int i1,i2;
}

But if I do that I'm not able to use the Contains function to check if a given pair is in the list. How can I do that so I can easily store integers in a List and check if a pair of integers already exists? I cannot use table because it is not known how many pairs there will be.

EDIT:
Forgot to add:
In my program pairs (x, y) and (y, x) are to be treated as equals.

EDIT:
(x,y) and (y,x) are equals while checking if Point is in the list, but x and y can not be swapped because x and y represent a connection between two points (integer is id of point, and no I can't use any reference etc...). When I'm checking if List contains a connection it is not important if it is (x,y) or (y,x) but later I would need that information.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

比忠 2024-10-13 04:59:37

如果您使用的是 .NET 4.0,则可以使用 Tuple 类,如

var tuple = new Tuple<int, int>(17, 42);
var otherTuple = Tuple.Create(17, 42);

var list = new List<Tuple<int, int>>();

请注意,如果您采用使用 Tuple 的路线,那么您将需要创建 IEqualityComparer> 的自定义实现,以反映 (x, y) 被视为等于 ( y,x)。然后,您必须将此比较器的实例传递给 List.Contains(T, IEqualityComparer) (此处 TTuple 为您服务)。

class TupleAsUnorderedPairComparer : IEqualityComparer<Tuple<TFirst, TSecond>> {
    public bool Equals(Tuple<TFirst, TSecond> x, Tuple<TFirst, TSecond> y) {
        if(Object.ReferenceEquals(x, y)) {
            return true;
        }
        if(x == null || y == null) {
            return false;
        }
        return x.Item1 == y.Item1 && x.Item2 == y.Item2 ||
               x.Item1 == y.Item2 && x.Item2 == y.Item1;
    }

    public int GetHashCode(Tuple<TFirst, TSecond> x) {
        if(x == null) {
            return 0;
        }
        return x.Item1.GetHashCode() ^ x.Item2.GetHashCode();
    }
}

否则,如果您不能或不想使用 Tuple,那么您需要为您的 Pair 实现 IEqualityComparer类或覆盖 Object.EqualsObject.GetHashCode

class Pair {
    public int First { get; private set; }
    public int Second { get; private set; }
    public Pair(int first, int second) {
        this.First = first;
        this.Second = second;
    }

    public override bool Equals(object obj) {
        if(Object.ReferenceEquals(this, obj)) {
            return true;
        }
        Pair instance = obj as Pair;
        if(instance == null) {
            return false;
        }
        return this.First == instance.First && this.Second == instance.Second ||
               this.First == instance.Second && this.Second == instance.First;
    }

    public override int GetHashCode() {
        return this.First.GetHashCode() ^ this.Second.GetHashCode();
    }
}

如果

class PairEqualityComparer : IEqualityComparer<Pair> {
    // details elided 
}

您使用

list.Contains(pair);

,那么它将使用 EqualsGetHashCode 但如果您使用

list.Contains(pair, new PairEqualityComparer);

,那么它将使用 PairEqualityComparer.EqualsPairEqualityComparer.GetHashCode 。请注意,这些可能与您的Object.EqualsObject.GetHashCode 实现不同。

最后,如果您经常进行遏制测试,那么 List 并不是您的最佳选择;您应该使用为此目的而设计的类,例如 HashSet

If you're using .NET 4.0, you could use the Tuple class as in

var tuple = new Tuple<int, int>(17, 42);
var otherTuple = Tuple.Create(17, 42);

and

var list = new List<Tuple<int, int>>();

Note that if you go the route of using Tuple<int, int> then you will need to create a custom implementation of IEqualityComparer<Tuple<TFirst, TSecond>> to reflect your equality rules that (x, y) be considered equal to (y, x). You will then have to pass an instance of this comparer to List<T>.Contains(T, IEqualityComparer<T>) (here T is Tuple<int, int> for you).

class TupleAsUnorderedPairComparer : IEqualityComparer<Tuple<TFirst, TSecond>> {
    public bool Equals(Tuple<TFirst, TSecond> x, Tuple<TFirst, TSecond> y) {
        if(Object.ReferenceEquals(x, y)) {
            return true;
        }
        if(x == null || y == null) {
            return false;
        }
        return x.Item1 == y.Item1 && x.Item2 == y.Item2 ||
               x.Item1 == y.Item2 && x.Item2 == y.Item1;
    }

    public int GetHashCode(Tuple<TFirst, TSecond> x) {
        if(x == null) {
            return 0;
        }
        return x.Item1.GetHashCode() ^ x.Item2.GetHashCode();
    }
}

Otherwise, if you can't or don't want to use Tuple then you will need to implement an IEqualityComparer<Pair> for your Pair class or override Object.Equals and Object.GetHashCode.

class Pair {
    public int First { get; private set; }
    public int Second { get; private set; }
    public Pair(int first, int second) {
        this.First = first;
        this.Second = second;
    }

    public override bool Equals(object obj) {
        if(Object.ReferenceEquals(this, obj)) {
            return true;
        }
        Pair instance = obj as Pair;
        if(instance == null) {
            return false;
        }
        return this.First == instance.First && this.Second == instance.Second ||
               this.First == instance.Second && this.Second == instance.First;
    }

    public override int GetHashCode() {
        return this.First.GetHashCode() ^ this.Second.GetHashCode();
    }
}

and

class PairEqualityComparer : IEqualityComparer<Pair> {
    // details elided 
}

If you use

list.Contains(pair);

then it will use Equals and GetHashCode but if you use

list.Contains(pair, new PairEqualityComparer);

then it will use PairEqualityComparer.Equals and PairEqualityComparer.GetHashCode. Note that these could be different than your implementations of Object.Equals and Object.GetHashCode.

Finally, if testing for containment is something that you'll be doing often then a List is not your best bet; you should use a class designed for that purpose like a HashSet.

放手` 2024-10-13 04:59:37

班级是你最好的选择。如果您执意使用 Contains 方法,则必须在 Pair 类中实现 IComparable 接口。这将使您能够确定这对整数的“相等”含义。

最简单的方法是创建现有的类,然后在 List 对象上创建和扩展方法。

public static bool ContainsIntegers(this List<Pair> targetList, Pair comparer) {
    foreach(Pair pair in targetList)
    {
        if(pair.i1 == comparer.i1 && pair.i2 == comparer.i2) return true;
    }
    return false;
}

The class is your best bet. If you're dead set on using the Contains method, you'll have to implement the IComparable interface in your Pair class. This will allow you to establish what "equality" means for this pair of integers.

The simplest way would be to create the class as you have and then create and extension method on the List<T> object.

public static bool ContainsIntegers(this List<Pair> targetList, Pair comparer) {
    foreach(Pair pair in targetList)
    {
        if(pair.i1 == comparer.i1 && pair.i2 == comparer.i2) return true;
    }
    return false;
}
∝单色的世界 2024-10-13 04:59:37

另一种方法是使用 List,通过将最大的数字放入高 32 位并将另一个数字放入低 32 位来填充它:

ulong MakeEntry(int i1, int i2)
{
    ulong hi = (ulong)Math.Max(i1, i2);
    ulong lo = (ulong)Math.Min(i1, i2);
    return (hi << 32) | lo;
}

List<ulong> items = new List<ulong>();

void DoSomething()
{
    // get numbers i1 and i2
    // and add to the list
    items.Add(MakeEntry(i1, i2));

    // test to see if the pair is in the list
    if (items.Contains(MakeEntry(i1, i2)))
    {
        // do whatever
    }
}

Another way to do this would be to use a List<ulong>, populating it by putting the largest number in the upper 32 bits and the other number in the lower 32 bits:

ulong MakeEntry(int i1, int i2)
{
    ulong hi = (ulong)Math.Max(i1, i2);
    ulong lo = (ulong)Math.Min(i1, i2);
    return (hi << 32) | lo;
}

List<ulong> items = new List<ulong>();

void DoSomething()
{
    // get numbers i1 and i2
    // and add to the list
    items.Add(MakeEntry(i1, i2));

    // test to see if the pair is in the list
    if (items.Contains(MakeEntry(i1, i2)))
    {
        // do whatever
    }
}
安穩 2024-10-13 04:59:37

改为创建一个向量2 的列表。
将该列表视为一对整数。

哈基?也许吧,但实际上比上面所有的要简单得多。

Make a list of vector2's instead.
Treat that list as a pair of ints.

Hacky? Maybe, but much simpler than all of that above really.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文