Remove 2 duplicated swap sublists in list - python

I have a two-dimensional list like this:
[[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
I want to remove all the sublists that are duplicates but in reverse order (ie: [1, 6] and [6, 1], [3, 7] and [7, 3]).
The result should be:
[[1, 6], [2, 5], [3, 7], [8, 9]]

You can use set and frozenset:
lst = [[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
output = set(map(frozenset, lst))
print(output)
# {frozenset({1, 6}), frozenset({2, 5}), frozenset({3, 7}), frozenset({8, 9})}
If you want to have a list of lists, then you can append the following:
output = list(map(list, output))
print(output)
# [[1, 6], [2, 5], [3, 7], [8, 9]]

You can do this easily by checking if the sorted list is already had already been added. Like this:
data = [[1, 6], [2, 5], [3, 7], [5, 2], [6, 1], [7, 3], [8, 9], [9, 8]]
new_data = []
for lst in data:
if sorted(lst) not in new_data:
new_data.append(lst)
print(new_data) # => [[1, 6], [2, 5], [3, 7], [8, 9]]
This works because [1, 6] and [6, 1] return the same sorted list.

Related

Why is my original 2D array being modified in the following code

Im trying to solve a coding problem where i have to generate some matrices, im new to python and i cant figure out why my matrix keeps getting changed to the latest matrix being generated. Here's the code i have so far:
def mirrorHorizontal(m):
l = list(m)
matrix_len = len(l)
for x in range(0,matrix_len):
temp = l[x][matrix_len-1]
l[x][matrix_len-1] = l[x][0]
l[x][0] = temp
return l
def mirrorVertical(m):
l = list(m)
matrix_len = len(l)
for x in range(0,matrix_len):
temp = l[0][x]
l[0][x] = l[matrix_len-1][x]
l[matrix_len-1][x] = temp
return l
def rotateMatrix(m):
l = list(m)
matrix_len = len(l)
rotated_matrix = []
for x in range(0,matrix_len):
rotated_row = []
for y in range(0, matrix_len):
rotated_row.append([(matrix_len-1) -y][y])
rotated_matrix.append(rotated_row)
return rotated_matrix
# Complete the formingMagicSquare function below.
def formingMagicSquare(s):
all_matrices = []
base_matrix = [[8,3,4],[1,5,9],[6,7,2]]
all_matrices.append(base_matrix)
print("all matrices after first append",all_matrices)
base_h_mirror = list(mirrorHorizontal(base_matrix))
print("horizontal_mirror",base_h_mirror)
all_matrices.append(base_h_mirror)
print("all matrices after first h mirror append",all_matrices)
base_v_mirror = list(mirrorVertical(base_matrix))
print("vertical_mirror",base_v_mirror)
all_matrices.append(base_v_mirror)
print("all matrices after first v mirror append",all_matrices)
#Same as vertical mirror of horizontal mirror
base_v_h_mirror = list(mirrorHorizontal(base_v_mirror))
all_matrices.append(base_h_mirror)
print("h_mirror added",all_matrices)
all_matrices.append(base_v_mirror)
print("h_mirror added",all_matrices)
all_matrices.append(base_v_h_mirror)
print("base_v_h_mirror added",all_matrices)
print("mirrored matrices= ",all_matrices)
matrix_len = len(all_matrices)
for x in range(0,matrix_len):
all_matrices.append(rotateMatrix(all_matrices[x]))
print(all_matrices)
formingMagicSquare()
The output , if you run it is something like:
all matrices after first append [[[8, 3, 4], [1, 5, 9], [6, 7, 2]]]
horizontal_mirror [[4, 3, 8], [9, 5, 1], [2, 7, 6]]
all matrices after first h mirror append
[
[[4, 3, 8], [9, 5, 1], [2, 7, 6]],
[[4, 3, 8], [9, 5, 1], [2, 7, 6]]
]
vertical_mirror [[2, 7, 6], [9, 5, 1], [4, 3, 8]]
all matrices after first v mirror append
[[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]],
[[2, 7, 6], [9, 5, 1], [4, 3, 8]]]
h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
base_v_h_mirror added [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
mirrored matrices= [[[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]], [[6, 7, 2], [1, 5, 9], [8, 3, 4]]]
Why is my matrix being populated with the same matrix again and again? I converted the list in the functions i used by slicing it [:]
This is also related to mutable and immutable types. You are dealing with lists of lists, which are lists of mutables. So the inner lists are passed by reference, even if you use [:] which makes a shallow copy: a copy of the container, but holding references to the inner object if they are mutables.
That's why, when you change the inner lists, you are changing the same inner lists each time. They are all references to the same lists.
Have a look at the copy docs to more details about shallow copies and deep copies. This will also give you a solution: use a deep copy.
In each function, replace:
l = list(m)
with:
l = copy.deepcopy(m)

Pairing up all possible objects in a list

Consider the following code:
list_example = [1,2,3,4,5,6,7,8,9]
List_of_ball_permutations = []
for i in list_example :
for j in list_example:
if j>i:
List_of_ball_permutations.append([i,j])
This will result in a list being formed as follows:
[[1, 2],
[1, 3],
[1, 4],
[1, 5],
[1, 6],
[1, 7],
[1, 8],
[1, 9],
[2, 3],
[2, 4],
[2, 5],
[2, 6],
[2, 7],
[2, 8],
[2, 9],
[3, 4],
[3, 5],
[3, 6],
[3, 7],
[3, 8],
[3, 9],
[4, 5],
[4, 6],
[4, 7],
[4, 8],
[4, 9],
[5, 6],
[5, 7],
[5, 8],
[5, 9],
[6, 7],
[6, 8],
[6, 9],
[7, 8],
[7, 9],
[8, 9]]
Whereby each number is paired with another number in the list and no repeats i.e. if [1,2] exists then [2,1] will not be created also pairs with two of the same numbers e.g. [1,1] will not be created either.
However now consider a list of objects whereby I would like to pair each object with one other object (not itself and no repeats) in a similar fashion as the numbers were. For some reason my code does not allow me to do that as it presents a message '>' not supported between instances of 'Ball' and 'Ball'. (The class I created was called Ball which generated the objects).
Any help to resolve this issue would be very much appreciated.
Of course, itertools is the proper "pythonic" solution:
import itertools
list(itertools.combinations(["a", "b", "c"], 2))
However, you have the correct idea, you can generate all the indices of the objects to be paired, and retrieve them:
def get_pairs(n):
for i in range(n) :
for j in range(i+1, n):
yield (i, j)
def get_objects_pairs(objects):
for first, second in get_pairs(len(objects)):
yield objects[first], objects[second]
objects = ['a', 'ball', 'toothbrush']
for pair in (get_objects_pairs(objects)):
print(pair)
output:
('a', 'ball')
('a', 'toothbrush')
('ball', 'toothbrush')

PYTHON: Move a value in a dictionary from one key to another key

If I have a dictionary say:
dictionary = {'blue': [ [0,1], [0,2] ] , 'red': [ [0,3], [0,4] ] }
How would I move a blue value say [0,1] to the red without leaving behind a copy in blue without hardcoding the delete ( so if I had a different list of a hundred values and want to move a value from one key to another it should also work in that way ).
I want the output to look this:
dictionary = {'blue': [ [0,2] ] , 'red': [ [0,3], [0,4], [0,1] ] }
EDIT:
Ok, since people are asking for context:
My dictionary is:
d = {' . ': [[0, 1], [0, 2], [0, 3], [0, 4], [0, 5], [0, 6], [0, 7], [0, 8], [0, 9], [1, 1],
[1, 2], [1, 3], [1, 4], [1, 5], [1, 6], [1, 7], [1, 8], [1, 9], [2, 1], [2, 2],
[2, 3], [2, 4], [2, 5], [2, 6], [2, 7], [2, 8], [2, 9], [3, 1], [3, 2], [3, 3],
[3, 4], [3, 5], [3, 6], [3, 7], [3, 8], [3, 9], [4, 0], [4, 1], [4, 2], [4, 3],
[4, 4], [4, 5], [4, 6], [4, 7], [4, 8], [4, 9], [5, 0], [5, 1], [5, 2], [5, 3],
[5, 4], [5, 5], [5, 6], [5, 7], [5, 8], [5, 9], [6, 0], [6, 1], [6, 2], [6, 3],
[6, 4], [6, 5], [6, 6], [6, 7], [6, 8], [6, 9], [7, 0], [7, 1], [7, 2], [7, 3],
[7, 4], [7, 5], [7, 6], [7, 7], [7, 8], [7, 9], [8, 0], [8, 1], [8, 2], [8, 3],
[8, 4], [8, 5], [8, 6], [8, 7], [8, 8], [8, 9], [9, 0], [9, 1], [9, 2], [9, 3],
[9, 4], [9, 5], [9, 6], [9, 7], [9, 8], [9, 9]],
' X ': [[0, 0], [1, 0], [2, 0], [3, 0]]}
I want to move [3,0] from ' X ' to ' . ' and don't want it being left behind there.
I don't want this hardcoded as I want to do so with other values back and forth.
Conditions to move values:
If a value has a certain neighbours
ie [1,0] neighbours are [0,0], [2,0], [0,1] and so on
so if it has a certain number of neighbours or doesn't I move it to either ' X ' or ' . '
This is so I can plot the coordinates with the corresponding label --> 'X' or '.'
I'm not sure if you're allowed to change the dictionary (this seems to be a homework assignment), but I think it would probably be better to store the coords as the keys and the symbols as the values of the dictionary.
# A dictionary comprehension to create a dict.
# Coords as the keys and '.' as the values.
board = {(x, y): '.' for x in range(10) for y in range(10)}
# To change the value just set some coords to 'X' or '.'.
board[(2, 3)] = 'X'
# Print the board.
for y in range(10):
for x in range(10):
print(board[(x, y)], end=' ')
print()
Maybe you could use tuples for internal lists and OrderedDict for external:
from collections import OrderedDict
dictionary = {'blue': OrderedDict.fromkeys([(0, 1), (0, 2)]),
'red': OrderedDict.fromkeys([(0, 3), (0, 4)])}
Then you could still iterate the values of the external dictionary one by one:
for pair in dictionary['blue']:
print(pair)
and inserting/deleting a pair would take O(1) on average.
Just a generic function to move values between keys. You should deal with the exception outside the function.
#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
def moveBetweenKeys(dictionary, src_key, dest_key, value):
"""
Move the value <value> from the key <src_key> to the key <dest_key>
Raises ValueError if the value was not found in the list of the keywork
<src_key>
"""
src_list = dictionary[src_key]
dest_list = dictionary[dest_key]
if value not in src_list:
raise ValueError("'%s' was not found in the list '%s'" % (value, src_key))
src_list.remove(value)
dest_list.append(value)

permutation of elements inside the list of list

I have a nested list as follows:
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
I need to permute only the elements inside each list.
do you have any idea how can I do this?
You can do something like this:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for x in A:
random.shuffle(x)
To shuffle each sublist in a list comprehension, you cannot use random.shuffle because it works in place. You can use random.sample with the sample length = the length of the list:
import random
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
new_a = [random.sample(l,len(l)) for l in A]
print(new_a)
an output:
[[2, 1, 3], [5, 4, 6], [7, 9, 8]]
That solution is the best one if you don't want to modify your original list. Else, using shuffle in a loop as someone else answered works fine as well.
Use permutations from itertools:
from itertools import permutations
A = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
out = []
for i in A:
for j in permutations(i):
out.append(list(j))
print out
OUTPUT:
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1],
[4, 5, 6], [4, 6, 5], [5, 4, 6], [5, 6, 4], [6, 4, 5], [6, 5, 4],
[7, 8, 9], [7, 9, 8], [8, 7, 9], [8, 9, 7], [9, 7, 8], [9, 8, 7]]

How do I make each list in the list of lists sort in ascending order?

I have the following lists:
[[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
And I am trying to sort them by the first value, after making the list go in ascending order:
Desired output:
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]
However, list.sort() only gives the following:
>>> mylist = [[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
>>> mylist.sort()
>>> mylist
[[1, 5], [2, 5], [3, 7], [4, 1], [4, 2], [6, 3], [7, 8]]
>>>
Of course, I could always loop each list in the list of lists and sort it:
>>> mylist
[[1, 5], [2, 5], [3, 7], [4, 1], [4, 2], [6, 3], [7, 8]]
>>> for k in range(len(mylist)):
... mylist[k] = sorted(mylist[k])
...
>>> mylist
[[1, 5], [2, 5], [3, 7], [1, 4], [2, 4], [3, 6], [7, 8]]
>>> sorted(mylist)
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]
But is there a one liner to solve this?
You can do:
sorted(sorted(sublist) for sublist in mylist)
This is a little better than your loop:
for sublist in mylist:
sublist.sort()
mylist.sort()
Of course, this changes each sublist in-place. Judging by your examples, it looks like that is what you want, but I thought I should mention it just in case.
Here is a one liner that does the sort in-place
>>> mylist = [[1, 5], [3, 7], [4, 2], [7, 8], [6, 3], [2, 5], [4, 1]]
>>> mylist.sort(key=lambda x:x.sort() or x)
>>> mylist
[[1, 4], [1, 5], [2, 4], [2, 5], [3, 6], [3, 7], [7, 8]]

Categories

Resources