Finding cycles in a dictionary

2024/10/7 22:30:21

I have a dictionary which has values as:

m = {1: 2, 7: 3, 2: 1, 4: 4, 5: 3, 6: 9}

The required output should be cyclic values like 1:2 -> 2:1 = cycle, which both are present in dictionary. 4:4 is also a cycle.

My output should be

[(1, 2), [4]]

CODE

m = {1: 2, 7: 3, 2: 1, 4: 4, 5: 3, 6: 9}
k = list(m.items())
print(k)p = [t[::-1] for t in k]
print(p)my_list = [(a, b) for (a, b) in p for (c, d) in k  if ((a ==c) and (b == d))]for i in k:if i in my_list:print("cycles : ", i)

OUTPUT:

The output I am getting is

cycles : (1, 2)
cycles : (2, 1)
cycles : (4, 4)

Can someone help me out with this?

Answer

Let's split this into two steps. First we'll find the cycles. Then we'll format the output however you want.

Finding cycles is easy, given that you have a dictionary: values become keys, making lookup fast. We can store the cycles in sorted order in a set to avoid duplicates:

cycles = set()
for k, v in m.items():if m.get(v) == k:cycles.add(tuple(sorted((k, v))))

Not that I'd recommend it, but the above can be written as an illegible one-liner:

cycles = set(tuple(sorted(item)) for item in m.items() if m.get(item[1]) == item[0])

Now to format the data. You want a list output, and entries with duplicates formatted as lists:

output = [[k] if k == v else (k, v) for k, v in cycles]

If you don't like clean code, you can imagine how to turn the whole operation into a one-liner :)

Update

It's worth considering the case where cycles are longer than one or two entries. You seem to want to store only one element per cycle, so let's do that. We can follow the chain from each element in the dictionary. If any part of the chain makes a cycle, we can find the minimum element of the cycle to report, and remove all the visited elements, since they are all no longer under consideration:

def find_cycles(m):n = m.copy()  # don't mutilate the originalcycles = []while n:visited = {}count = 0k, v = n.popitem()while v is not None:visited[k] = (count, v)count += 1k = vv = n.pop(k, None)if k in visited:cycle_start = visited[k][0]item = min((k, v) for k, (c, v) in visited.items() if c >= cycle_start)cycles.append(item)return [[k] if k == v else (k, v) for k, v in cycles]

For example:

>>> find_cycles({1:2, 2:3, 3:4, 4:5, 5:1, 6:1, 7:1, 8:8})
[(1, 2), [8]]

A better generalization might be to return a tuple with the entire cycle in it, starting with the smallest key. Mostly the statements under if k in visited: need to change to do that:

    visited[k] = count...if k in visited:if len(visited) == 1:cycle = list(visited.keys())else:cycle_start = visited[k]cycle = sorted((c, k) for k, c in visited.items() if c >= cycle_start)cycle = tuple(k for c, k in cycle)k = min(range(len(cycle)), key=lambda x: cycle[x])cycle = cycle[k:] + cycle[:k]cycles.append(cycle)return cycles

This version is more informative:

>>> find_cycles({1:2, 2:3, 3:4, 4:5, 5:1, 6:1, 7:1, 8:8})
[(1, 2, 3, 4, 5), [8]]

Here is my IDEOne scratchspace in case you're interested: https://ideone.com/6kpRrW

https://en.xdnf.cn/q/118771.html

Related Q&A

Create a dataframe from HTML table in Python [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.Want to improve this question? Update the question so it focuses on one problem only by editing this post.Closed 9…

Unable to load a Django model from a separate directory in a database script

I am having difficulty writing a python script that takes a directory of .txt files and loads them into my database that is utilized in a Django project. Based on requirements the python script needs …

Leetcode problem 14. Longest Common Prefix (Python)

I tried to solve the problem (you can read description here: https://leetcode.com/problems/longest-common-prefix/) And the following is code I came up with. It gives prefix value of the first string in…

Python BS: Fetching rows with and without color attribute

I have some html that looks like this (this represents rows of data in a table, i.e the data between tr and /tr is one row in a table)<tr bgcolor="#f4f4f4"> <td height="25"…

Python multiple number guessing game

I am trying to create a number guessing game with multiple numbers. The computer generates 4 random numbers between 1 and 9 and then the user has 10 chances to guess the correct numbers. I need the fee…

How to produce a graph of connected data in Python?

Lets say I have a table of words, and each word has a "related words" column. In practice, this would probably be two tables with a one-to-many relationship, as each word can have more than o…

Syntax for reusable iterable?

When you use a generator comprehension, you can only use the iterable once. For example.>>> g = (i for i in xrange(10)) >>> min(g) 0 >>> max(g) Traceback (most recent call la…

Buildozer Problem. I try to make apk file for android, but i cant

artur@DESKTOP-SMKQONQ:~/Suka$ lsbuildozer.spec main.pyartur@DESKTOP-SMKQONQ:~/Suka$ buildozer android debugTraceback (most recent call last):File "/usr/local/bin/buildozer", line 10, in <…

how to run python script with ansible-playbook?

I want to print result in ansible-playbook but not working. python script: #!/usr/bin/python3import timewhile True:print("Im alive")time.sleep(5)deploy_python_script.yml:connection: localbeco…

How to concatenate pairs of row elements into a new column in a pandas dataframe?

I have this DataFrame where the columns are coordinates (e.g. x1,y1,x2,y2...). The coordinate columns start from the 8th column (the previous ones are irrelevant for the question) I have a larger exam…