convert string into 2 dimensional list with no imports - python

I need to convert a string representation into a 2 dimensional list.
I am trying to read inputs from a text file. All inputs follow a standard format where each line represents a different variable. When I read the following line from the input file using f.readline():
[[0, 2, 1, 2, 3, 0], [2, 0, 3, 0, 1, 0], [2, 0, 0, 3, 3, 0], [0, 2, 3, 0, 0, 3], [1, 2, 3, 1, 0, 2], [2, 1, 0, 1, 3, 0]]
This line is read in as a string, but I need it converted to a 2 dimensional list. A constraint for this project is I cannot use any packages, only base python.
How do I do this?

Something like that should work:
text = "[[0, 2, 1, 2, 3, 0], [2, 0, 3, 0, 1, 0], [2, 0, 0, 3, 3, 0], [0, 2, 3, 0, 0, 3], [1, 2, 3, 1, 0, 2], [2, 1, 0, 1, 3, 0]]"
output = []
for sublist in text.split('], '):
sublist = sublist.replace('[', '').replace(']', '')
data = []
for number in sublist.split(', '):
data.append(int(number))
output.append(data)
print(output)
Using list comprehension:
text = "[[0, 2, 1, 2, 3, 0], [2, 0, 3, 0, 1, 0], [2, 0, 0, 3, 3, 0], [0, 2, 3, 0, 0, 3], [1, 2, 3, 1, 0, 2], [2, 1, 0, 1, 3, 0]]"
output = [[int(number) for number in sublist.replace('[', '').replace(']', '').split(', ')] for sublist in text.split('], ')]
print(output)

This short script should work:
string_lists = "[[0, 2, 1, 2, 3, 0], [2, 0, 3, 0, 1, 0], [2, 0, 0, 3, 3, 0], [0, 2, 3, 0, 0, 3], [1, 2, 3, 1, 0, 2], [2, 1, 0, 1, 3, 0]]"
parsed_list = string_lists[1:-2].split("], ") # remove last 2 brackets and then split into lists
for index, row in enumerate(parsed_list):
parsed_list[index] = row[1:].split(", ") # split sublists into individual elements
parsed_list[index] = [int(num) for num in parsed_list[index]] # cast each element to int
print(parsed_list)
Note that you don't have to create additional list like I did, you can just work on your starting string (just change "parsed_list" to "string_lists" everywhere in above script)

Let's see some pattern firstly. We have:
[ [a1, a2, ..., ap1], [b1, b2, ..., bp2], ..., [xx1, xx2, ..., xxpn] ].
we have to select some separator which will help us divide it into groups. I'd prob go for ], [ but you can choose even ],
so we have to remove [[ and ]] from our string to have clear pattern.
inp.strip('[]')
we split it into sublists
inp.strip('[]').split('], [')
now every sublist in format:
a1, a2, ..., ap1
we split it on , so we will get items.
sublist.split(', ')
We summarize it and take as one list comprehension:
list_from_string = [[int(item) for item in sublist.split(', ')] for sublist in inp.strip('[]').split('], [')]

What a fun problem! Found this simple solution that iterates the string only once:
output_list = list() # Contains the output
inner_list = None # Current "row"/"column"
current_value = "" # Keep track of the current value
for char in list_as_text[1:-1]:
if char == " ":
# Ignore spaces
continue
elif char.isdigit(): # Add `or char == "."` to support float values
# Found a digit, keep track of the current value
current_value += char
elif char == ",":
# Found a comma, save the value in inner_list
inner_list.append(int(current_value)) # Use `float(current_value)` to support float values
# Start a new current_vale
current_value = ""
elif char == "[":
# We start a new inner_list
inner_list = list()
elif char == "]":
# We completed an inner_list
output_list.append(inner_list)

Here is a step-by-step approach using split(), rstrip() and lstrip() methods of the string datatype:
row = '[[0, 2, 1, 2, 3, 0], [2, 0, 3, 0, 1, 0], [2, 0, 0, 3, 3, 0], [0, 2, 3, 0, 0, 3], [1, 2, 3, 1, 0, 2], [2, 1, 0, 1, 3, 0]]'
listOfStrings = [s.rstrip(' ,]') for s in row.split('[')]
listOfStrings = [s for s in listOfStrings if len(s) > 0]
listOfLists = [[int(n.lstrip(' ')) for n in s.split(',')] for s in listOfStrings]
print(listOfLists)
Line 1 creates a string containing comma-separated values for each list in the original with some extra empty strings.
Line 2 eliminates the empty strings.
Line 3 creates a list of lists of numbers.

Related

Does the .append and .insert function edit objects inserted into lists?

oldrow = [1]
for i in range(5):
finaloutputlist.append(oldrow)
print(oldrow)
oldrow.append(0)
oldrow.insert(0,0)
j = i + 1
newrow = []
for i in range(len(oldrow) -1):
#print(oldrow[i])
newrow.append(oldrow[i] + oldrow [i+1])
oldrow = newrow
print(finaloutputlist)
When I run the above code, I get an output of
[1]
[1, 1]
[1, 2, 1]
[1, 3, 3, 1]
[1, 4, 6, 4, 1]
[[0, 1, 0], [0, 1, 1, 0], [0, 1, 2, 1, 0], [0, 1, 3, 3, 1, 0], [0, 1, 4, 6, 4, 1, 0]]
There when I print "oldrow", I get exactly the array that I want to append onto my list of arrays in called finaloutputlist .But appending that same oldrow keeps netting me the final output line. For some reason the 0s that I add after updating my finaloutputlist seem to be making their way onto the list.
Thank you to #jasonharper,
finaloutputlist.append(oldrow.copy())
worked amazing, no extra imports needed

Python - two-dimensional array adressing fills up the whole array

I have a problem. First let me show you the code:
def neon(l):
oc = 0; #naj ocena
tz = 0; #teraz ocena
#sprawdzanie poziomo
for x in range(len(l[0])):
for i in range(len(l[x])):
for y in range(i + 1,len(l[x])):
tz = l[x][i] + l[x][y] + (max(y - x, x - y) + 1) * 2;
if (tz > oc):
oc = tz;
pion = [[0] * len(l[0])] * len(l);
print(pion);
print("#######");
for i in range(len(pion)):
for y in range(len(pion[i])):
pion[i][y] = l[y][i];
print(pion);
neon([[1,2,1,2],[7,1,7,1],[1,1,1,1],[3,3,3,3]]);
The problem is that when i try to adress pion[i][y] instead of just changing that value from 0 to whatever the program changes the value in all of the inner arrays with the second index y. This is how it looks:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
#######
[[1, 7, 1, 3], [1, 7, 1, 3], [1, 7, 1, 3], [1, 7, 1, 3]]
[[2, 1, 1, 3], [2, 1, 1, 3], [2, 1, 1, 3], [2, 1, 1, 3]]
[[1, 7, 1, 3], [1, 7, 1, 3], [1, 7, 1, 3], [1, 7, 1, 3]]
[[2, 1, 1, 3], [2, 1, 1, 3], [2, 1, 1, 3], [2, 1, 1, 3]]
Instead, it should be:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
#######
[[1, 7, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
[[1, 7, 1, 3], [2, 1, 1, 3], [0, 0, 0, 0], [0, 0, 0, 0]]
[[1, 7, 1, 3], [2, 1, 1, 3], [1, 7, 1, 3], [0, 0, 0, 0]]
[[1, 7, 1, 3], [2, 1, 1, 3], [1, 7, 1, 3], [2, 1, 1, 3]]
Please help and thank you in advance.
This problem occurs due to the following reasons:
pionis a list of inner lists. Each element of pion just holds the reference to one inner list.
Because of the way you have created and initialized pion (using pion = [[0] * len(l[0])] * len(l)), all elements of pion hold references to the same inner list. So, in pion, instead of many distinct inner lists, you just have multiple references to a single inner list. In other words, pion[0], pion[1], pion[2], etc, are all references to the same inner list of zeros. Any modification that you make to this inner list, using a particular row index (eg, using the expression pion[3]), will be visible through all the other row indexes also, because, at all row indexes, you are just holding a reference to the same inner list.
To correct this, you need to create and initialize the list differently. Eg, if rows and cols are respectively the number of rows and columns, you could do something like this:
pion = [([0]*cols) for i in range(rows)]

Grouping 0s and 1s in python

I have an array of zeros and ones like [0,0,0,1,1,1,0,0,0,1,1]. How to write a program to save neighboring 0's and 1's in different arrays.
E.g.
[0,0,0,1,1,1,0,0,0,1,1] giving [0,0,0],[1,1,1],[0,0,0],[1,1].
You can group them with itertools.groupby, like this
>>> data = [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1]
>>> from itertools import groupby
>>> [list(group) for item, group in groupby(data)]
[[0, 0, 0], [1, 1, 1], [0, 0, 0], [1, 1]]
The result of groupby, will be a tuple of actual item and an iterator which gives the grouped items. We just convert the grouped items to a list, with list(group).
As per the comments,
>>> data = [1, 2, 1, 3, 4, 5, 6, 7, 1, 2, 3]
>>> flag = [0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1]
Create a generator which will give the values multiplied,
>>> gen = (d * v for d, v in zip(data, flag))
Now, group based on the result of calling bool on each of the numbers. So, if the bool is called on 0, it will give False, otherwise True.
>>> [list(g) for _, g in groupby(gen, key=bool)]
[[0, 0, 0], [3, 4, 5], [0, 0, 0], [2, 3]]

join sublist in a list of lists with python

I am a newbie to python and have been having an issue with list comprehension. Is there a way to extend subsists in a list of list like this
lst = [[0,0,0,0],[[x,x,x,x],[y,y,y,y]],[0,0,0,0],[0,0,0,0]]
I would like to end up with a following list, but I am not sure how to approach the problem:
lst = [[0,0,0,0],[x,x,x,x,y,y,y,y],[0,0,0,0],[0,0,0,0]]
I found this snippet of code but I am not sure how to make it operate on a second "level" of lists. I tried this:
print([x for y in lst for x in y])
Just go through each element and if it has a length of 2 (which means its a donut), add the two elements of that sublist together.
def flatten(data):
new_data = [lists[0]+lists[1] if len(lists) == 2 else lists for lists in data]
return new_data
data = [[1, 2, 3, 4], [[5, 6, 7, 8], [9, 10, 11, 12]], [13, 14, 15, 16]]
new_data = flatten(data)
For the example given, you can do as follows:
x,y=1,2
lst = [[0,0,0,0],[[x,x,x,x],[y,y,y,y]],[0,0,0,0],[0,0,0,0]]
map(lambda l: sum(l,[]) if isinstance(l[0],list) else l, lst)
#gives: [[0, 0, 0, 0], [1, 1, 1, 1, 2, 2, 2, 2], [0, 0, 0, 0], [0, 0, 0, 0]]
I assumed that x=1, and y=2.
Based on the image, it seems you have nested lists in the following way:
x,y=1,2
lst = [[[0,0,0,0]],[[[x,x,x,x],[y,y,y,y]]],[[0,0,0,0]],[[0,0,0,0]]]
# 0, x, and y in you case are lists/touples, but for this example there are ints.
# it should not matter anyway for this example.
map(lambda l: [sum(l[0],[])] if len(l[0])==2 else l, lst)
# relults in: [[[0, 0, 0, 0]], [[1, 1, 1, 1, 2, 2, 2, 2]], [[0, 0, 0, 0]], [[0, 0, 0, 0]]]

Insert value dynamically in 2D list python

I am having a two dimensional list like:
[[1, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 1, 1, 0], [1, 1, 1, 1]]
and I want to XOR the inner sub-lists with each other. So at some point of time with some combination I will be getting a sub list with all zeros like [0,0,0,0] and if I don't get with two sub lists I have to go for XORing of three sub-lists till I get again [0,0,0,0], if not then, have to go for four sub-lists.
The problem is I can do like picking up two lists and XOR each element then save it in separate sub-list and this works but each time I have to change my code so is there any way to XOR sub-list like [1, 1, 0, 0] ^ [1, 0, 1, 0] instead of doing like lis[i][j]^lis[i+1][j] so that I can manage my code recursively?
You could find shorter but I think this would work:
STOP=[0,0,0,0]
def nxor(l,res=None,p=1):
if not res: res= l[0]
if res == STOP:
return p-1 # or l[:p]
try:
return nxor(l,list(iter.imap (operator.xor, *list([res,l[p]]) )),p+1)
except:
return None # or res
print nxor (l)
It returns the position of the last sub-list that lead to [0,0,0,0]; it would be easy to return the sub-list instead, or the actual result (see comments).
If you want to test all the combinations, you could use itertools:
for i in xrange(2,len(l)):
for j in itertools.combinations(l,i):
print nxor(list(j))
What you could do is to convert the 2-D bit lists to a 1-D number list and then XOR them together.
a = [[1, 1, 0, 0], [1, 0, 1, 0], [0, 1, 1, 0], [1, 1, 1, 0], [1, 1, 1, 0], [0, 1, 1, 0], [1, 1, 1, 1]]
b = map(lambda x: int("".join(map(lambda y: str(y), x)),2), a)
b is now: [12, 10, 6, 14, 14, 6, 15]
Now you are working with a 1-D list which will make that easier.

Categories

Resources