I have a list of numbers and I want to extract N elements as lists, and store them in another list.
Example:
list1 = [1,2,3,4,5,6,7,8,9]
resultList = [[1,2,3],[4,5,6],[7,8,9]]
I've done the following
def getLines(square, N):
i = 0
line = [None]*N
lines = list()
for elt in square:
line[i] = elt
i += 1
if i == N:
lines.append(line)
i = 0
return lines
Why do I always get the last list three times
[[7,8,9],[7,8,9],[7,8,9]]
when I call the function getLines(list1, 3).
I also tried to eliminate the temporary list and add the elements directly to resultList like this:
def getLines(square, N):
i = 0
j = 0
lines = [[None]*N]*N # Need to be initialized to be able to index it.
for elt in square:
lines[i][j] = elt
j += 1
if j == N:
i += 1
j = 0
return lines
The last group is still appearing N times. Any hints on how to fix that?
This is because you are creating only one inner list object, and altering it.
In pseudocode, what you are doing is:
Create a list called line assigning [None, None, None] to it
Create an empty list called lines
For three times:
-- Pick n items from the square list
-- Assign these three items to line[0], line[1] and line[2]
-- Append line to lines
So, what you are doing is assigning to individual items of line. This is important - you're not making a new object each time, you're changing individual items in the line list.
At the end of it all, line will point to the list [7, 8, 9]. And you can see lines as being substantially [line, line, line] (a list of three times the same object), so specifically now it will point to [[7,8,9], [7,8,9], [7,8,9]].
To solve this, possibly the solution that most keeps your original code is to re-define line after appending it. This way, the variable name line will refer to a different list each time, and you won't have this problem.
def getLines(square, N):
i = 0
line = [None]*N
lines = list()
for elt in square:
line[i] = elt
i += 1
if i == N:
lines.append(line)
line = [None]*N # Now `line` points to a different object
i = 0
return lines
Of course, there is leaner, more Pythonic code that can do the same thing (I see that an answer has already been given).
EDIT - Ok, here goes a somehow more detailed explanation.
Perhaps one of the key concepts is that lists are not containers of other objects; they merely hold references to other objects.
Another key concept is that when you change an item in a list (item assignment), you're not making the whole list object become another object. You're merely changing a reference inside it. This is something we give for granted in a lot of situations, but somehow becomes counter-intuitive when we'd want things to go the other way and "recycle" a list.
As I was writing in the comments, if list was a cat named Fluffy, every time you're appending you're creating a mirror that points to Fluffy. So you can dress Fluffy with a party hat, put a mirror pointing to it, then give Fluffy a clown nose, put on another mirror, then dress Fluffy as a ballerina, add a third mirror, and when you look at the mirrors, all three of them will show the ballerina Fluffy. (Sorry Fluffy).
What I mean is that in practice in your first script, when you do the append:
lines.append(line)
by the first concept I mentioned, you are not making lines contain the current status of line as a separate object. You are appending a reference to the line list.
And when you do,
line[i] = elt
by the second concept, of course line is always the same object; you're just changing what's referenced at the i-th position.
This is why, at the end of your script, lines will appear to "contain three identical objects": because you actually appended three references to the same object. And when you ask to see the content of lists, you will read, three times, the list object in its current status.
In the code I provided above, I re-define the name lists to make it reference a brand new list every time it's been appended to lists:
lines.append(line)
line = [None]*N # Now `line` points to a different object
This way, at the end of the script I have "three different cats" appended, and each one was conveniently named Fluffy just until I had appended it, to give room for a new Fluffy list after that.
Now, in your second script, you do something similar. The key instruction is:
lines = [[None]*N]*N # Need to be initialized to be able to index it.
In this line, you are creating two objects:
- the list [None, None, None]
- the list named lines, which contains N references to the same list [None, None, None].
What you did was just to create straight away Fluffy and the three mirrors pointing at him.
In fact if you change lines[0][2], or lines[1][2], you're just changing the same item [2] of your same Fluffy.
What you actually wanted to do is,
lines = [[None]*N for i in range(N)]
which creates three different cats - I mean, lists, and have lines point to the three.
You might consider solving this like:
def getLines(square, N):
return [square[i:i + N] for i in range(0, len(square), N)]
For example: getLines([1, 2, 3, 4, 5, 6, 7, 8, 9], 3) will return [[1, 2, 3], [4, 5, 6], [7, 8, 9]], or getLines([1, 2, 3, 4, 5, 6, 7, 8, 9], 2) results in [[1, 2], [3, 4], [5, 6], [7, 8], [9]], and so on.
Related
I have a set of list,
list_0=[a,b,a,b,b,c,f,h................]
list_1=[f,g,c,g,f,a,b,b,b,.............]
list_2=[...............................]
............
list_j=[...............................]
where j is (k-1), with some thousands of value stored in them. I want to count for how many times a specific value is in a specific list. And I can have only 8 different values (I mean, every single element of those list can only have one out of 8 specific values, let's say a,b,c,d,e,f,g,h; so I want to count for every list how many times there's the value a, how many times the value b, and so on).
This is not so complicated.
What is complicated, at least for me, is to change on the fly the name of the list.
I tried:
for i in range(k):
my_list='list_'+str(int(k))
a_sum=exec(my_list.count(a))
b_sum=exec(my_list.count(b))
...
and it doesn't work.
I've read some other answer to similar problem, but I' not able to translate it to fit my need :-(
Tkx.
What you want is to dynamically access a local variable by its name. That's doable, all you need is locals().
If you have variables with names "var0", "var1" and "var2", but you want to access their content without hardcoding it. You can do it as follows:
var0 = [1,2,3]
var1 = [4,5,6]
var2 = [7,8,9]
for i in range(3):
variable = locals()['var'+str(i)]
print(variable)
Output:
[1, 2, 3]
[4, 5, 6]
[7, 8, 9]
Although doable, it's not advised to do this, you could store those lists in a dict containing their names as string keys, so that later you could access them by simply using a string without needing to take care about variable scopes.
If your names differ just by a number then perhaps you could also use a list, and the number would be the index inside it.
let's say I have a list defined in Kotlin:
val mylist = mutableListOf<List<Int>>(listOf(2,3,5), listOf(2,5,6))
Now, I want to assign a certain value to one of these sublists. For example, now that I have a list of
((2,3,5)(2,5,6))
I would like my list to be
((2,3,5)(2,100,6))
I'm used to doing this in Python by something like myList[1][1] = 100. How do I achieve the same result in Kotlin?
Kotlin has two sets of collection interfaces, the regular List, Set, etc. which are read-only, and the same ones with the Mutable prefix, which can be modified.
listOf will give you a List instance, while mutableListOf gives you a MutableList instance. If you use the latter for creating your nested lists, you can use the exact syntax you've asked about:
val mylist: MutableList<MutableList<Int>> = mutableListOf(mutableListOf(2,3,5), mutableListOf(2,5,6))
mylist[1][1] = 100
println(mylist) // [[2, 3, 5], [2, 100, 6]]
(I've added the explicit type for myList for clarity's sake, it can be omitted from the left side of the assignment.)
In short i want to number chars in order from 1 to n without changing the position of the chars in a list.
Suppose I have a list called key = ['c', 'a', 't'] How would i go about
assigning a number to each letter depending on where it is situated in the alphabet with respect to the other letters. Starting at 1 and going until len(key) such that our key becomes [ 2, 1, 3]
I'm really stumped. I have a way to convert them to numbers but very unsure as to how to compare them such that the above happens any help, tips, ideas or explanations would be appreciated.
this is what i have so far...
import string
key = list(input("enter key: ").upper())
num = []
for i in key:
num.append(string.ascii_uppercase.index(i)+1)
This solution assumes that duplicate entries should be assigned the same number, so that
# ['c','a','t'] -> [2, 1, 3]
# ['c','a','t','c','a','t'] -> [2, 1, 3, 2, 1, 3]
You can write a simple function like this:
def get_alphabet_pos(lst):
uniques = sorted(set(lst)) # set() to filter uniques, then order by value
numbers = {letter: i+1 for i, letter in enumerate(uniques)} # build a lookup dict
return [numbers[key] for key in lst]
get_alphabet_pos('cat') # [2, 1, 3]
So here's what happens in the function:
In line 1 of the function we convert your list to a set to remove any duplicate values. From the docs # https://docs.python.org/3/tutorial/datastructures.html#sets:
A set is an unordered collection with no duplicate elements.
Still in line 1 we sort the set and convert it back into a list. Thanks to #StefanPochmann for pointing out that sorted() takes care of the list conversion.
In line 2, we use enumerate() so we can iterate over the indices and values of our list of unique values: https://docs.python.org/3/library/functions.html#enumerate
The rest of line 2 is a simple dict comprehension to build a dictionary of letter -> number mappings. We use the dictionary in line 3 to look up the numbers for each letter in our input dict.
You might have to modify this slightly depending on how you want to handle duplicates :)
I am stuck trying to understand the mechanics behind this combined input(), loop & list-comprehension; from Codegaming's "MarsRover" puzzle. The sequence creates a 2D line, representing a cut-out of the topology in an area 6999 units wide (x-axis).
Understandably, my original question was put on hold, being to broad. I am trying to shorten and to narrow the question: I understand list comprehension basically, and I'm ok experienced with for-loops.
Like list comp:
land_y = [int(j) for j in range(k)]
if k = 5; land_y = [0, 1, 2, 3, 4]
For-loops:
for i in the range(4)
a = 2*i = 6
ab.append(a) = 0,2,4,6
But here, it just doesn't add up (in my head):
6999 points are created along the x-axis, from 6 points(x,y).
surface_n = int(input())
for i in range(surface_n):
land_x, land_y = [int(j) for j in input().split()]
I do not understand where "i" makes a difference.
I do not understand how the data "packaged" inside the input. I have split strings of integers on another task in almost exactly the same code, and I could easily create new lists and work with them - as I understood the structure I was unpacking (pretty simple being one datatype with one purpose).
The fact that this line follows within the "game"-while-loop confuses me more, as it updates dynamically as the state of the game changes.
x, y, h_speed, v_speed, fuel, rotate, power = [int(i) for i in input().split()]
Maybe someone could give an example of how this could be written in javascript, haskell or c#? No need to be syntax-correct, I'm just struggling with the concept here.
input() takes a line from the standard input. So it’s essentially reading some value into your program.
The way that code works, it makes very hard assumptions on the format of the input strings. To the point that it gets confusing (and difficult to verify).
Let’s take a look at this line first:
land_x, land_y = [int(j) for j in input().split()]
You said you already understand list comprehension, so this is essentially equal to this:
inputs = input().split()
result = []
for j in inputs:
results.append(int(j))
land_x, land_y = results
This is a combination of multiple things that happen here. input() reads a line of text into the program, split() separates that string into multiple parts, splitting it whenever a white space character appears. So a string 'foo bar' is split into ['foo', 'bar'].
Then, the list comprehension happens, which essentially just iterates over every item in that splitted input string and converts each item into an integer using int(j). So an input of '2 3' is first converted into ['2', '3'] (list of strings), and then converted into [2, 3] (list of ints).
Finally, the line land_x, land_y = results is evaluated. This is called iterable unpacking and essentially assumes that the iterable on the right has exactly as many items as there are variables on the left. If that’s the case then it’s just a nice way to write the following:
land_x = results[0]
land_y = results[1]
So basically, the whole list comprehension assumes that there is an input of two numbers separated by whitespace, it then splits those into separate strings, converts those into numbers and then assigns each number to a separate variable land_x and land_y.
Exactly the same thing happens again later with the following line:
x, y, h_speed, v_speed, fuel, rotate, power = [int(i) for i in input().split()]
It’s just that this time, it expects the input to have seven numbers instead of just two. But then it’s exactly the same.
I have the following question for homework
Define a function append lists that
takes a list of lists and returns a
new list containing the sublist
values. For example, append lists([[1,
2], [3, 4], [5]]) should return the
list [1, 2, 3, 4, 5] and append
lists([[1, 2], [3], [[4, 5]]]) should
return the list [1, 2, 3, [4, 5]].
I've tried various ways of creating this function in order to append the list so it gives the desired output to no avail so I came here looking for some help. I've found a few other ways of going about this online, but they use extensive methods that we haven't even dabbled in as of yet in my CPSC 121 class. We're limited to the basics in what we've learned.
Any help would be much appreciated!
By now, it is likely that the assignment is gone, but here is a solution:
def append_lists(lists):
output = []
for l in lists:
for e in l:
output.append(e)
return output
This appends each element of each list to the output of the function, which eliminates exactly one level of nesting in the elements.