Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 给定一个完全由字符串元组列表表示的线性顺序,将该顺序作为字符串列表输出_Python - Fatal编程技术网

Python 给定一个完全由字符串元组列表表示的线性顺序,将该顺序作为字符串列表输出

Python 给定一个完全由字符串元组列表表示的线性顺序,将该顺序作为字符串列表输出,python,Python,给定形式为[(a,b),…]的项目对,其中(a,b)表示a>b,例如: [('best','better'),('best','good'),('better','good')] 我想输出一个表单列表: ['best','better','good'] 出于某种原因,这很难做到。有什么想法吗 ============================代码============================= 我知道它为什么不起作用 def to_rank(raw): rank = [

给定形式为
[(a,b),…]
的项目对,其中
(a,b)
表示
a>b
,例如:

[('best','better'),('best','good'),('better','good')]
我想输出一个表单列表:

['best','better','good']
出于某种原因,这很难做到。有什么想法吗

============================代码=============================

我知道它为什么不起作用

def to_rank(raw):

  rank = []

  for u,v in raw:
    if u in rank and v in rank:
      pass

    elif u not in rank and v not in rank:
      rank = insert_front (u,v,rank)
      rank = insert_behind(v,u,rank)

    elif u in rank and v not in rank:
      rank = insert_behind(v,u,rank)

    elif u not in rank and v in rank:
      rank = insert_front(u,v,rank)

  return [[r] for r in rank]

# @Use: insert word u infront of word v in list of words
def insert_front(u,v,words):
  if words == []: return [u]
  else:
    head = words[0]
    tail = words[1:]
    if head == v: return [u] + words
    else        : return ([head] + insert_front(u,v,tail))

# @Use: insert word u behind word v in list of words
def insert_behind(u,v,words):
  words.reverse()
  words = insert_front(u,v,words)
  words.reverse()
  return words
=========================更新===================

根据许多人的建议,这是一个直接的拓扑排序设置,我最终决定使用来自以下来源的代码:algocoding.wordpress.com/2015/04/05/topology-sorting-python/

这解决了我的问题

def go_topsort(graph):
in_degree = { u : 0 for u in graph }     # determine in-degree 
for u in graph:                          # of each node
    for v in graph[u]:
        in_degree[v] += 1

Q = deque()                 # collect nodes with zero in-degree
for u in in_degree:
    if in_degree[u] == 0:
        Q.appendleft(u)

L = []     # list for order of nodes

while Q:                
    u = Q.pop()          # choose node of zero in-degree
    L.append(u)          # and 'remove' it from graph
    for v in graph[u]:
        in_degree[v] -= 1
        if in_degree[v] == 0:
            Q.appendleft(v)

if len(L) == len(graph):
    return L
else:                    # if there is a cycle,  
    return []      

RockBilly的解决方案也适用于我的情况,因为在我的设置中,对于每个v(u,v)。所以他的答案不是很“计算机科学”,但在这种情况下,它完成了工作

如果列表完整,意味着有足够的信息进行排名(也没有重复或冗余输入),这将起作用

from collections import defaultdict
lst = [('best','better'),('best','good'),('better','good')]

d = defaultdict(int)

for tup in lst:
    d[tup[0]] += 1
    d[tup[1]] += 0 # To create it in defaultdict

print sorted(d, key = lambda x: d[x], reverse=True)
# ['best', 'better', 'good']
只要给他们点,每次你在列表中遇到左一点,就增加左一点


编辑:我确实认为OP具有确定的输入类型。始终具有组合nCr(n,2)的元组计数。这是一个正确的解决方案。无需抱怨边缘案例,我已经知道了答案(并提到了)。

您要找的是。您可以使用深度优先搜索(我链接的wiki中包含伪代码)在线性时间内完成此操作。

如果您根据列表项进行排序或创建词典,您将错过@Rockybilly在其回答中提到的顺序。我建议您从原始列表的元组创建一个列表,然后删除重复项

def remove_duplicates(seq):
    seen = set()
    seen_add = seen.add
    return [x for x in seq if not (x in seen or seen_add(x))]

i = [(5,2),(1,3),(1,4),(2,3),(2,4),(3,4)]
i = remove_duplicates(list(x for s in i for x in s))
print(i)  # prints [5, 2, 1, 3, 4]

j = [('excellent','good'),('excellent','great'),('great','good')]
j = remove_duplicates(list(x for s in j for x in s))
print(j)  # prints ['excellent', 'good', 'great']
见参考资料:


有关
remove_duplicates()
函数的说明,请参见此。

您可以利用以下事实:列表中排名最低的项永远不会出现在任何元组的开头。您可以提取此最低项,然后从列表中删除包含此最低项的所有元素,然后重复以获取下一个最低项

即使您有多余的元素,或者列表比这里的一些示例更稀疏,这也应该有效。我将其分解为寻找排名最低的项目,然后使用它创建最终排名的繁重工作

from copy import copy

def find_lowest_item(s):
    #Iterate over set of all items
    for item in set([item for sublist in s for item in sublist]):
        #If an item does not appear at the start of any tuple, return it
        if item not in [x[0] for x in s]:
            return item

def sort_by_comparison(s):
    final_list = []
    #Make a copy so we don't mutate original list
    new_s = copy(s)
    #Get the set of all items
    item_set = set([item for sublist in s for item in sublist])
    for i in range(len(item_set)):
        lowest = find_lowest_item(new_s)
        if lowest is not None:
            final_list.insert(0, lowest)
        #For the highest ranked item, we just compare our current 
        #ranked list with the full set of items
        else:
            final_list.insert(0,set(item_set).difference(set(final_list)).pop())
        #Update list of ranking tuples to remove processed items
        new_s = [x for x in new_s if lowest not in x]
    return final_list

list_to_compare = [('black', 'dark'), ('black', 'dim'), ('black', 'gloomy'), ('dark', 'gloomy'), ('dim', 'dark'), ('dim', 'gloomy')]
sort_by_comparison(list_to_compare)
[‘黑色’、‘暗淡’、‘黑暗’、‘阴郁’]

[“最好”、“更好”、“好”]

[“最好”、“更好”、“好”]


这里有一个方法。它基于使用完整的成对排序来生成一个旧式(早期Python 2)
cmp
函数,然后使用
functools.cmp\u to\u key
将其转换为适合Python 3排序方法的

import functools

def sortByRankings(rankings):
    def cmp(x,y):
        if x == y:
            return 0
        elif (x,y) in rankings:
            return -1
        else:
            return 1

    items = list({x for y in rankings for x in y})
    items.sort(key = functools.cmp_to_key(cmp))
    return items
测试结果如下:

ranks = [('a','c'), ('b','a'),('b','c'), ('d','a'), ('d','b'), ('d','c')]
print(sortByRankings(ranks)) #prints ['d', 'b', 'a', 'c']

请注意,要正确工作,参数
排名
必须包含每对不同项目的条目。如果没有,则在将其提供给此函数之前,首先需要计算所具有的对的传递闭包。

如果指定了完整的语法,则可以简单地计算项目数:

>>> import itertools as it
>>> from collections import Counter
>>> ranks = [('best','better'),('best','good'),('better','good')]
>>> c = Counter(x for x, y in ranks)
>>> sorted(set(it.chain(*ranks)), key=c.__getitem__, reverse=True)
['best', 'better', 'good']
如果语法不完整,则可以构建一个图和
dfs
所有路径来查找最长的路径。这并不是很低效,因为我还没有想过:):



我们可以假设您的输入列表是完整的吗?也就是说,它包含定义顺序所需的所有比较?似乎您需要首先计算传递闭包,可能使用Warshall算法,然后根据得到的总数进行排序order@AndrewGuy是的,这个假设是正确的。你认为元组列表会有多大?您正在寻找的算法的性能有多重要?@SimeonVisser Index很好,列表的平均长度为6。
排序(d)
将按键排序,而不是按数值排序。@SimeonVisser啊,请原谅我的无聊。@Rockybilly它适用于三项列表,但不适用于四项列表?例如:[('black','dark'),('black','dim'),('black','Dame'),('dark','dark'),('dim','Dally')]输出['black','dark','dim','Dally','Dally'],但是应该输出['black','dim','dark','Dally']@chibro2以前的版本是错误的,请再试一次。@Rockybilly明白了!谢谢,孩子,我从来没有想过这个解决办法。太优雅了。你把一件简单的事情提升到了一个新的水平!!你能解释一下这有多简单吗?我只是给出了他所问问题的名称。OP不需要拓扑排序或DFS!!这可以通过更简单的代码实现,而不是OP是否需要拓扑排序的问题。拓扑排序不是解决方案。这是他问的问题的名称。一个可能的解决方案是DFS。他当然不需要,但这是一个简单的方法。谢谢,将问题分类有时是最重要的步骤。我不认为这是他要求的。最后一个示例的输出应该是“优秀”、“更好”、“好”@LawrenceWu您在哪里找到了
更好的
?我的代码的输入是
[('excellent','good'),('excellent','great'),('great','good')]
,答案是正确的。不要通过观察输出来判断解决方案,看代码。我的意思是“很棒”。是的,输出仍然错误。仔细阅读问题-如果元组(great,good)在输入中,那么great需要在good之前出现。OP没有提到这一点,我已经仔细阅读了问题。此外,好出现在伟大之前,因为好(第一次出现在元组1中)出现在伟大(第一次出现在元组2中)之前。我没有改变列表中的顺序,所以输出应该是正确的。这是目前唯一正确的答案(这是kahns算法的实现,尽管它可能不是线性时间实现)。接受这一点就好了。计数是解决问题的一种优雅而简单的方法
ranks = [('a','c'), ('b','a'),('b','c'), ('d','a'), ('d','b'), ('d','c')]
print(sortByRankings(ranks)) #prints ['d', 'b', 'a', 'c']
>>> import itertools as it
>>> from collections import Counter
>>> ranks = [('best','better'),('best','good'),('better','good')]
>>> c = Counter(x for x, y in ranks)
>>> sorted(set(it.chain(*ranks)), key=c.__getitem__, reverse=True)
['best', 'better', 'good']
def dfs(graph, start, end):
    stack = [[start]]
    while stack:
        path = stack.pop()
        if path[-1] == end:
            yield path
            continue
        for next_state in graph.get(path[-1], []):
            if next_state in path:
                continue
            stack.append(path+[next_state])

def paths(ranks):
    graph = {}
    for n, m in ranks:
        graph.setdefault(n,[]).append(m)
    for start, end in it.product(set(it.chain(*ranks)), repeat=2):
        yield from dfs(graph, start, end)

>>> ranks = [('black', 'dark'), ('black', 'dim'), ('black', 'gloomy'), ('dark', 'gloomy'), ('dim', 'dark'), ('dim', 'gloomy')]
>>> max(paths(ranks), key=len)
['black', 'dim', 'dark', 'gloomy']
>>> ranks = [('a','c'), ('b','a'),('b','c'), ('d','a'), ('d','b'), ('d','c')]
>>> max(paths(ranks), key=len)
['d', 'b', 'a', 'c']