c#list交叉不按预期工作

时间:2015-04-16 11:17:30

标签: c#

我使用此方法创建一些数组并将它们存储在列表块中:

private void CreateBlocks()
    {
        if (size == 1)
        {
            blocks.Add(pos);
        }
        else if (orientation == "vert")
        {
            for (int i = 0; i < size; i++)
            {
                blocks.Add(new int[]{pos[0] + i, pos[1]});
            }
        }
        else
        {
            for (int i = 0; i < size; i++)
            {
                blocks.Add(new int[] { pos[0], pos[1] + i });
            }
        }
    }

我尝试使用此代码在shipsPos列表中存储块列表数组(如果shipsPos中不存在任何数组:

private void AddShips(int numberOfShips)
    {
        while (numberOfShips > 0)
        {
            Ship ship = new Ship();
            if (!shipsPos.Intersect(ship.Blocks).Any())
            {
                ships.Add(ship);
                shipsPos.AddRange(ship.Blocks);
                shipTypes[ship.Size] += 1;
                numberOfShips--;
            }
        }
    }

ShipCreateBlocks方法所属的类。我的问题是,即使shipsPos中已经存在一个数组,它也会被添加到列表中。我究竟做错了什么?

1 个答案:

答案 0 :(得分:4)

通过引用比较数组,以便具有相同元素的两个数组不等于相等。因此.Intersect(...)将它们视为单独的数组。

试试这段代码:

var xs = new [] { new [] { 1, 2 }, new [] { 3, 4 } };
var ys = new [] { new [] { 1, 2 }, new [] { 5, 6 } };

var zs = xs.Intersect(ys); // 0 elements!

这表明.Intersect(...)未选择数组作为元素。

要使.Intersect(...)能够使用嵌套数组,您需要实现自己的IEqualityComparer<T[]>。这是一个简单的问题:

public class ArrayComparer<T> : IEqualityComparer<T[]>
{
    public bool Equals(T[] ts0, T[] ts1)
    {
        return ts0.SequenceEqual(ts1);
    }

    public int GetHashCode(T[] ts)
    {
        return ts.Aggregate(0, (a, t) => (a >> 2) + t.GetHashCode());
    }
}

现在你可以这样做:

var zs = xs.Intersect(ys, new ArrayComparer<int>()); // 1 element!