我有一个元组列表,其中每个元组中的第一个项目是沿着路线的起始距离,第二个项目是沿着该路线的结束距离。
∃b. int (card b) ≤ FINISHED
列表中的第一项从点0到点100,第二项从点100到150,依此类推。
但是,我希望通过聚合那些连续的项目来简化此列表。这会将列表缩小为: PhoneNumberUtil phoneUtil = PhoneNumberUtil.getInstance();
boolean isPossible = phoneUtil.isPossibleNumber("+16475550123", "US");
这样做的最佳方式是什么?
答案 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)]