Finding changes made to lists [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 11 months ago.
Improve this question
So I'm trying to find the items that went in and went out of a list before and after it changed
For example, at first my list is:
[1, 1, 2, 5, 7, 7]
And then a minute later it's:
[1, 2, 2, 5, 6, 7, 4]
How would I end up with 2 lists that show what items went out and which went in like so,
itemsOut = [1,7]
itemsIn = [2, 6, 4]
Position and length can change

You can use Counter from the built-in collections module:
>>> list1 = [1, 1, 2, 5, 7, 7]
>>> list2 = [1, 2, 2, 5, 6, 7, 4]
>>> from collections import Counter
>>> counter1 = Counter(list1)
>>> counter2 = Counter(list2)
>>> l_diff = counter1-counter2
>>> r_diff = counter2-counter1
>>> print(list(l_diff))
[1, 7]
>>> print(list(r_diff))
[2, 6, 4]

You could use something like this, to detect wich items changed.
old_arr = [1, 2, 2, 5, 7, 7]
new_arr = [1, 1, 2, 5, 7, 7]
items_out = []
for element in old_arr:
if new_arr.count(element) > 0:
new_arr.pop(new_arr.index(element))
else:
items_out.append(element)
print("Items out:", items_out)
print("Items in:", new_arr)

Related

Python: list.remove() behave wiredly [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 10 months ago.
Improve this question
def get_variables(cells):
domains = [1,2,3,4]
variables = {}
for cell in cells:
if(cell == "C11"):
variables[cell] = [1]
elif(cell == "C22"):
variables[cell] = [2]
elif(cell == "C33"):
variables[cell] = [3]
elif(cell == "C44"):
variables[cell] = [4]
else:
variables[cell] = domains
cells = ['C'+x+y for x in "1234" for y in "1234"]
variables = get_variables(cells)
csp = CSP(variables, constraints, assigned)
pprint(csp.variables)
csp.variables["C12"].remove(1)
print(csp.variables["C13"])
output:
{'C11': [1],
'C12': [1, 2, 3, 4],
'C13': [1, 2, 3, 4],
'C14': [1, 2, 3, 4],
'C21': [1, 2, 3, 4],
'C22': [2],
'C23': [1, 2, 3, 4],
'C24': [1, 2, 3, 4],
'C31': [1, 2, 3, 4],
'C32': [1, 2, 3, 4],
'C33': [3],
'C34': [1, 2, 3, 4],
'C41': [1, 2, 3, 4],
'C42': [1, 2, 3, 4],
'C43': [1, 2, 3, 4],
'C44': [4]}
[2, 3, 4]
It is supposed to remove 1 from "C12", instead it did it to "C13". Why is that? I guess something related to memory location? This really drives me crazy. Any suggestion would be appreciated!
I suppose that "C12" and "C13" don't contain different lists, but the same one. Meaning that no matter how you modify either one, the other will be affected in the same way.
To see this clearly, print csp.variables at the end instead of just "CSP12".
The mistake is this line:
variables[cell] = domains
Because every variable[cell] is given the same list. Which is a mutable type. So when it is modified, it will be modified in place.
To fix this you could give the cells copies or slices, which are different objects:
variables[cell] = domains.copy()
or
variables[cell] = domains[:]
try this
desired_key = 'C12'
for key in csp.keys():
if key == desired_key:
del csp[key][0]
print(csp)
``

replace variables in a list with combinations of elements [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 3 years ago.
Improve this question
I want to replace variables in a list with combination of elements.
To be more specific:
I have these two lists
liste1 = [1,2,3,'X','X',4]
liste2 = [5,6,7]
and I want to get a list containing the elements below :
[1,2,3,5,6,4]
[1,2,3,5,7,4]
[1,2,3,6,7,4]
[1,2,3,6,5,4]
[1,2,3,7,5,4]
[1,2,3,7,6,4]
Does anyone have an idea how to make it ?
You can do it this way:
from itertools import permutations
liste1 = [1, 2, 3, 'X', 'X', 4]
liste2 = [5, 6, 7]
def replacements(liste1, liste2):
x_indices = [i for i, val in enumerate(liste1) if val == 'X']
nb = len(x_indices)
for perm in permutations(liste2, nb):
l1 = liste1[:] # if we want to preserve the original and yield different lists
for i, new_val in zip(x_indices, perm):
l1[i] = new_val
yield l1
for r in replacements(liste1, liste2):
print(r)
Output:
[1, 2, 3, 5, 6, 4]
[1, 2, 3, 5, 7, 4]
[1, 2, 3, 6, 5, 4]
[1, 2, 3, 6, 7, 4]
[1, 2, 3, 7, 5, 4]
[1, 2, 3, 7, 6, 4]
We first list the indices where 'X' appears, then generate the permutations of as many elements of liste2. For each permutation, we replace the 'X's.

Why does the insert function and concatenation do this? [duplicate]

This question already has answers here:
What do ellipsis [...] mean in a list?
(5 answers)
Closed 5 years ago.
x = [4, 5, 6]
li = [1, 2, 3, 7]
li.insert(3,x)
x+=li
print(x)
The output is:
[4, 5, 6, 1, 2, 3, [...], 7]
I'm new to python/coding and I don't know what these ellipses are but when I do other code it starts getting weird. Wasn't sure what to ask since I have no clue what's going on. Thank you!
you're inserting a list inside your list, probably not what you want.
Then when doing this
x+=li
the representation of the list then shows an ellipsis because you're referencing the list from itself (x is referenced in li already)
To insert several items at once in a list in-place you could use slice assignment:
>>> x = [4, 5, 6]
>>> li = [1, 2, 3, 7]
>>> li[3:3] = x
>>> li
[1, 2, 3, 4, 5, 6, 7]

Pythonic way to find all elements with the highest frequency? [duplicate]

This question already has answers here:
How to find most common elements of a list? [duplicate]
(11 answers)
Closed 6 years ago.
I have a list such as this:
lst = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4]
I would like to find all the elements which occur most frequently.
So I would like:
most = [1, 3, 5]
1, 3, and 5 would occur the most, which is 4 times. What's a fast, pythonic way to do this? I tried methods shown here:
How to find most common elements of a list?.
But it only gives me the top 3, I need all elements. Thank you.
With collections.Counter and a list comprehension:
from collections import Counter
lst = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4]
r = [x for x, _ in Counter(lst).most_common(3)]
print(r)
# [1, 3, 5]
You can generalize for values with highest count by using max on the counter values:
c = Counter(lst)
m = max(c.values())
r = [k for k in c if c[k] == m]
print(r)
# [1, 3, 5]
For large iterables, to efficiently iterate through the counter and stop once the required items have been taken, you can use itertools.takewhile with most_common without any parameters:
from itertools import takewhile
c = Counter(lst)
m = max(c.values())
r = [x for x, _ in takewhile(lambda x: x[1]==m, c.most_common())]
print(r)
# [1, 3, 5]
You gain by not having to iterate through all the items in the counter object, although there is some overhead with having to sort the items using most_common; so I'm sure if this absolutely efficient after all. You could do some experiments with timeit.
You can also get the same result with groupby from itertools module and list comprehension in this way:
from itertools import groupby
a = [1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4]
most_common = 3
final = [k for k,v in groupby(sorted(a), lambda x: x) if len(list(v)) > most_common]
Output:
print(final)
>>> [1, 3, 5]
You can do the following if you like to print all the most frequent,
from collections import Counter
words=[1, 3, 5, 1, 5, 6, 1, 1, 3, 4, 5, 2, 3, 4, 5, 3, 4]
most= [word for word, word_count in Counter(words).most_common()]
print (most)
>>>
[1, 3, 5, 4, 2, 6]
Please note, if you want to limit, you can enter the number inside most_common() function. Ex: ...most_common(3)]. Hope this answers your question.

Union of two lists in Python [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have two lists say:
a = [1, 2, 2, 2, 3]
b = [2, 5, 6]
After doing a union, I should get something like this (don't mind the order):
c = [1, 2, 2, 2, 3, 5, 6]
The final list should contain common elements only once and rest of elements (from both lists) should be copied as they are. Sets can't be used for this as they remove multiple occurrence of an element from the list, which isn't a union. What is a Pythonic way to do so?
Perform a union, keeping repetition:
>>> c = a + b
[1, 2, 2, 3, 2, 5, 6]
Perform a union, keeping repetition & order:
>>> c = sorted(a + b)
[1, 2, 2, 2, 3, 5, 6]
Perform an union, no repetition in each list, but repetition allowed in final union, and keeped order:
>>> c = sorted(list(set(a)) + list(set(b)))
[1, 2, 2, 3, 5, 6]
After clarification of the question, the goal is to build a list that take elements (including repetition) of, and then add elements of b if they are not in the new list.
>>> c = a + [e for e in b if e not in a]
[1, 2, 2, 2, 3, 5, 6]
After another clarification of the question, the goal is to build a list containing all elements of input list. But, if elements are in common, they are pushed the same number there
>>> from collections import Counter
>>> def merge(a,b):
... na, nb = Counter(a), Counter(b)
... return list(Counter({k: max((na[k], nb[k])) for k in set(a + b)}).elements())
>>> merge([1, 2, 2, 2, 3], [2, 5, 6])
[1, 2, 2, 2, 3, 5, 6]
>>> merge([1, 2, 3], [2, 2, 4])
[1, 2, 2, 4]

Categories

Resources