基于连续点简化元组列表

时间:2015-12-21 21:00:25

标签: python

我有一个元组列表,其中每个元组中的第一个项目是沿着路线的起始距离,第二个项目是沿着该路线的结束距离。

∃b. int (card b) ≤ FINISHED

列表中的第一项从点0到点100,第二项从点100到150,依此类推。

但是,我希望通过聚合那些连续的项目来简化此列表。这会将列表缩小为: PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance(); boolean isPossible = phoneUtil.isPossibleNumber("+16475550123", "US");

这样做的最佳方式是什么?

3 个答案:

答案 0 :(得分:1)

使用生成器,您可以使用以下内容执行此操作:

def aggregate(tuples):
    current = None
    for (x, y) in tuples:
        if current == None:
            current = (x, y)
        else:
            (a, b) = current
            if b == x:  # should this be b >= x?
                current = (a, y)
            else:
                yield current
                current = (x, y)
    if current != None:
        yield current

在函数式编程方面,这有一个结构性的习惯用法可以被称为foldl,它对所有流都是通用的。你会写在Haskell,

aggregate (x:xs) = reverse $ foldl chomper [x] xs where
    chomper output@((a, b) : rest) element@(x, y)
        | x == b     = (a, y) : rest 
        | otherwise  = element : output

换句话说,你也可以在Python中使这个具体到列表并改为编写:

def foldl(fn, a, bs):
    """Fold a list from the left with `fn`. 

    This is a left fold, it takes an (A, B) -> A function and an A and a 
    list of Bs and produces an A."""
    z = a
    for b in bs:
        z = fn(z, b)
    return z

def chomper(output, element):
    (a, b) = output.pop()
    (x, y) = element
    if x == b:
        output.append((a, y))
    else:
        output.append((a, b))
        output.append(element)
    return output

答案 1 :(得分:1)

这是一个简短而简洁的方法:

>>> l = [(0, 100), (100, 150), (150, 180), (180, 190), (400, 450), (450, 700)]
>>> l1, l2 = zip(*l)
>>> zip((i for i in l1 if not i in set(l2)), (i for i in l2 if i not in set(l1)))
[(0, 190), (400, 700)]

通过一点递归也很容易,但循环会导致无限递归:

def follow(d):
    # this finds the correct "ending" given a start point in the mapping
    follow_inner = lambda x: d[x] if d[x] not in d else follow_inner(d[x])
    for start in d:
        if start in d.values():
            # skip "linking" items
            continue
        yield start, follow_inner(start)

像这样使用:

lst = [(0,100),(100,150),(150,180),(180,190),(400,450),(450,700)]
filtered = list(follow(dict(lst)))
print filtered
# [(0, 190), (400, 700)]

有明显的改进,这只是一个POC。你也可以只使用发电机(我觉得更合适) - 但我这样做很有趣: - )

答案 2 :(得分:0)

MyTuples = [(0, 100), (100, 150), (150, 180), (180, 190), (400, 450), (450, 700)]



def con(l):
    it = iter(l)
    # pull first tuple
    tmp,  prev = next(it,((),()))
    for a, b in it:
        # compare prev b to current  a if they are != the sequence is broken
        if prev != a:
            yield tmp, prev
            tmp = a
        # update prev
        prev = b
    yield tmp, prev
print(list(con(MyTuples)))

输出:

[(0, 190), (400, 700)]