python 中特殊向量之间的关系

Relations between special vectors in python

我想知道是否有办法在一些特殊的 "vectors" 之间建立关系。

示例:

假设这些是我的向量(我只会选择 3 个特殊向量):

   a=[1,2,[1]]
   b=[1,2,[2]]
   c=[1,3,[1]]

并且我想在比较它们时添加以下规则(字典顺序):

我想说

   a<b 

因为

  a[0]=b[0] and a[1]=b[1] but *a[2]<b[2]*

但我也想说

  a<c

因为

  a[0]=b[0] and a[1]<c[1] and a[2]<=c[2]

但请注意,"b" 和 "c" 的情况略有不同,因为它们不可比较,因为即使

  b[0]=c[0] and b[1]<c[1], the last term changes everything since b[2]>c[2]

换句话说,我正在应用的规则将首先比较两个向量 x 和 y 的 "normal" 个条目,如果向量 x 的某个条目大于向量 y 的某个条目,我们看看最后一个条目。如果向量x的最后一项大于或等于,那么我们说x>y,如果不是这样,那么x和y不可比。

如果 x 和 y 的所有 "normal" 条目都相同,我们比较最后一个条目。如果 x 的最后一个条目大于 y 的最后一个条目,我们也说 x>y。

我认为这与 while 循环有关。

您可以轻松编写一个函数来执行您描述的操作。

def special_lt(vec1, vec2):

您已将 "normal" 值定义为除最后一个以外的所有值,并将 "special" 值定义为最后一个,所以这很简单:

    normal1, normal2 = vec1[:-1], vec2[:-1]
    special1, special2 = vec1[-1], vec2[-1]

现在,如果我没理解错的话,你想对正常值进行字典顺序比较,然后在它们相等时遵从特殊值...

    if normal1 == normal2:
        return special1 < special2

… 但除此之外,使用特殊值作为检查以确保它们的排序方式与正常值相同:

    elif normal1 < normal2:
        if special1 <= special2:
            return True
        raise ValueError('not comparable')
    else:
        if special2 <= special1:
            return False
        raise ValueError('not comparable')

请注意,为了比较正常值列表和特殊值列表,我没有使用循环;我只是比较了列表。那是因为列表已经按字典顺序进行了比较(当然,在内部,这是通过循环完成的,但我不必编写它)。

您可以使 vector 成为 list 的子 class 并重载 __lt____gt__ 方法,以便在默认行为。还要重载 __le____ge__ 方法以确保完整性:

class vector(list):
    def __lt__(self, other):
        lt = super().__lt__(other)
        if lt and self[-1] > other[-1]:
            return False
        return lt
    def __gt__(self, other):
        gt = super().__gt__(other)
        if gt and self[-1] < other[-1]:
            return False
        return gt
    def __le__(self, other):
        if self == other:
            return True
        return self < other
    def __ge__(self, other):
        if self == other:
            return True
        return self > other

这样:

a=vector([1,2,[1]])
b=vector([1,2,[2]])
c=vector([1,3,[1]])
print(a<b)
print(a<c)
print(b<c)
print(c<b)
print(b>c)
print(c>b)
print(b<=c)
print(c<=b)

将输出:

True
True
False
False
False
False
False
False

编辑:鉴于下面的评论,我还想指出,在这种情况下 functools.total_ordering 不起作用,因为非典型OP 要求的逻辑,其中一个对象可以同时不小于、不大于和不等于另一个对象。

因此,如果我们只为 vector class 定义 __lt__ 方法并应用 total_ordering 装饰器:

from functools import total_ordering
@total_ordering
class vector(list):
    def __lt__(self, other):
        lt = super().__lt__(other)
        if lt and self[-1] > other[-1]:
            return False
        return lt

上面的测试代码会产生以下不正确的输出:

True
True
False
False
False
True
True
False