Python enumeration function enumerate takes one argument start.
What is the use of this argument ?
If i write some code using this argument it shifts only index e.g.
>>a=[2,3,4,5,6,7]
>>for index,value in enumerate(a,start=2):
... print index,value
...
**2 2**
3 3
4 4
5 5
6 6
7 7
8 8
So index is changed to 2 ,Not Value.Value is still started from first element. Why this is so ? In place of this functionality ,It could be better if value is started from that index rather than starting element.
What was the thinking behind the implementation of this ?
enumerate() associates a sequence of integers with an iterable, i.e. it enumerates the items of the sequence. Its argument start is not meant to affect the starting position within the iterable, just the initial value from which to start counting.
One use is to start the enumeration from 1 instead of 0, e.g. if you wanted to number the lines in a file:
with open('file.txt') as f:
for line_number, line in enumerate(f, 1):
print(line_number, line)
This outputs the line numbers starting from 1, which is where most users would expect line numbering to begin.
If you want to skip the first n items in a sequence you can just slice it:
a = [2,3,4,5,6,7]
n = 2
for index, value in enumerate(a[n:]):
print index, value
outputs
0 4
1 5
2 6
3 7
but you might like to start the enumeration from 3 as well:
a = [2,3,4,5,6,7]
n = 2
for index, value in enumerate(a[n:], n+1):
print index, value
which would output
3 4
4 5
5 6
6 7
Some people - most I suppose - aren't used to an enumerated list starting at zero. At the very least, this makes it easy to format the output so the enumeration starts at one, e.g.
a = ['Fred', 'Ted', 'Bob', 'Alice']
for index, value in enumerate(a, start=1):
print index, value
will print out:
1 Fred
2 Ted
3 Bob
4 Alice
Without the start=1 parameter, enumerate(a) would print
0 Fred
1 Ted
2 Bob
3 Alice
https://docs.python.org/2/library/functions.html#enumerate
Related
What are the possible ways of reversing order of any output?
For example, if I have a code like this:
for i in range(10):
print(i)
This is fairly a simple example of course. I can just say
for i in range(9, -1, -1):
print(i)
But what happens when you have very complicated functions, lists, maps, arrays, etc. So my question is: Is there a generic way (or ways) to reverse the order of any output?
I've been thinking about pushing every element (element can be anything) onto a stack, then pop() elements and printing the popped element. But maybe there are better solutions
You can use the reversed builtin:
for i in reversed(range(10)):
print(i)
output:
9
8
7
6
5
4
3
2
1
0
for i in range(10)[::-1]:
print(i)
OUTPUT
9
8
7
6
5
4
3
2
1
0
I have a list of numbers in a python data frame and want to group these numbers by a specific range and count. The numbers range from 0 to 20 but lets say there might not be any number 6 in that case I want it to show 0.
dataframe column looks like
|points|
5
1
7
3
2
2
1
18
15
4
5
I want it to look like the below
range | count
1 2
2 2
3 1
4 1
5 2
6 0
7 ...
8
9...
I would iterate through the input lines and fill up a dict with the values.
All you have to do then is count...
import collections
#read your input and store the numbers in a list
lines = []
with open('input.txt') as f:
lines = [int(line.rstrip()) for line in f]
#pre fill the dictionary with 0s from 0 to the highest occurring number in your input.
values = {}
for i in range(max(lines)+1):
values[i] = 0
# increment the occurrence by 1 for any found value
for val in lines:
values[val] += 1
# Order the dict:
values = collections.OrderedDict(sorted(values.items()))
print("range\t|\tcount")
for k in values:
print(str(k) + "\t\t\t" + str(values[k]))
repl: https://repl.it/repls/DesertedDeafeningCgibin
Edit:
a slightly more elegant version using dict comprehension:
# read input as in the first example
values = {i : 0 for i in range(max(lines)+1)}
for val in lines:
values[val] += 1
# order and print as in the first example
I am writing a test that needs to plug in values from a list to a peripheral going forwards then backwards sequentially without breaking the loop. here is the structure I need to modify:
exampleList = [5 10 60 9 3]
for i, listValue in enumerate(exampleList):
self.log += 'Status: iteration {0}, sending {1}\n'.format(i, listValue)
self.device.writeToPeripheral(listValue)
...
I am trying to essentially write [5 10 60 9 3 3 9 60 10 5] (single or extra middle value doesn't matter) to an external device. Changing the list contents will mess up critical objects elsewhere in the environment for different tests. Is there a creative way in python to structure the loop to iterate going up the list, then back down immediately after? I could simply put this in a function and reverse the list after the first call, but I would like to avoid this approach if possible.
One way is to use itertools.chain() like:
Code:
import itertools as it
exampleList = [5, 10, 60, 9, 3]
forward_back = it.chain(exampleList, reversed(exampleList))
for i, list_value in enumerate(forward_back):
print i, list_value
Results:
0 5
1 10
2 60
3 9
4 3
5 3
6 9
7 60
8 10
9 5
Another option is to append the reversed list when iterating:
for i, list_value in enumerate(exampleList + exampleList[::-1]):
I have a set of values vertically
2,4
4,7
5,8
9
I want to have binary combination of each two values in vertical for example 2 and 4, 2 and 5 etc . the same for the second
2 4
2 5
4 5
4 7
4 8
.
.
.
Ok it seems very complicated so I try to make it easier
I convert my data into horizon
I have
2,4,5
4,7,8,9
I want to have the binary combination of the first row
2 4
2 5
4 5
and the the binary combination of the second row
4 7
4 8
4 9
7 8
7 9
8 9
If you have values stores in two collectables, use list comprehension
from itertools import izip_longest
a = [(1,'a'),(2,'b'),(3,None)]
b,c = izip_longest(*a)
d = [(i, j) for i in b if i for j in c if j]
I think I understand. Try this code:
test.py
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# these are two lists
list1 = [2, 4, 5]
list2 = [4, 7, 8, 9]
two_items_side_by_side(list1)
two_items_side_by_side(list2)
When you run this, your results will look like so:
Result
python test.py
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
If your test case is a string with each line containing comma separated text like this, you can use test2.py as an example
2,4
4,7
5,8
,9
test2.py
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# process the data and store them into a list
# then do the same work as we did in the first example
def convert_data_into_lists():
lines = data.split('\n')
for line in lines:
# ignore empty lines
if len(line.strip()) < 1:
continue
# split by comma and ignore if we don't get 2 or more values
items = line.split(',')
if len(items) < 2:
continue
# put first item in list1 and second item in list2
if len(items[0].strip()) > 0: list1.append(items[0].strip())
if len(items[1].strip()) > 0: list2.append(items[1].strip())
# -------------------------------------------------------------------
# this is my string
data = """
2,4
4,7
5,8
,9
"""
list1 = []
list2 = []
convert_data_into_lists()
two_items_side_by_side(list1)
two_items_side_by_side(list2)
Result
python test2.py
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
There are more elegant ways to write this code. I have written it in a manner that will help you understand the code and try it out yourself.
Requirement change
Based on the change in requirement, data is in a text file. We will take three test cases (see in results). To accommodate the requirements, I am going to use the same code I used in test2.py. Instead of creating individual lists for each column we have in our text file, I will create one list that will dynamically contain as many lists as you have columns in your text file.
Code
#!/bin/python
# put items side by side
# take first item and put the next item besides it
# if there are any more items after the next, put that item besides the first item
# if there are no more items after the next, switch to the next item in the list
# repeat
def two_items_side_by_side(mylist):
list_len = len(mylist)
for i in range(list_len):
for j in range(i+1, list_len):
print '{} {}'.format(mylist[i], mylist[j])
# -------------------------------------------------------------------
# process the data and store them into a list
# then do the same work as we did in the first example
def convert_data_into_lists():
with open(data) as f:
lines = f.readlines()
for line in lines:
# ignore empty lines
if len(line.strip()) < 1:
continue
# split by comma and ignore if we don't get 2 or more values
items = line.split(',')
counter = 0
for item in items:
if len(mylist) < counter + 1:
mylist.append([])
if len(item.strip()) > 0:
mylist[counter].append(item.strip())
counter += 1
# -------------------------------------------------------------------
# this is my string
data = 'test.txt'
mylist = []
convert_data_into_lists()
for individual_list in mylist:
two_items_side_by_side(individual_list)
Result
Case 1
Data:
2,4
4,7
5,8
,9
Results:
2 4
2 5
4 5
4 7
4 8
4 9
7 8
7 9
8 9
Case 2
Data:
2,4
4,7
5,8
6,9
Results:
2 4
2 5
2 6
4 5
4 6
5 6
4 7
4 8
4 9
7 8
7 9
8 9
Case 3
Data:
2,4,10
4,7,11
5,8,
,9,13
Results:
2 4
2 5
2 6
4 5
4 6
5 6
4 7
4 8
4 9
7 8
7 9
8 9
10 11
10 13
11 13
EDIT
By modifying the code above to only use a single parameter, we can read the contents of a csv file and (using some form of delimiter) provide combinations across the entire data set. Just call total_zipper() and replace 'filename.txt' with your file name.
def total_zipper():
def zipper(a):
lst = []
for i in range(1,len(a)+1):
lst+=zip(a,a[i:])
return sorted(lst)
f = open('filename.txt','r')
return [zipper(line) for line in f]
This treats all lines as iterables (Strings). For readline() to work, I believe you need a return statement at the end of each line in the txt. See the input/output page for Python for more.
Here's the shortest version I could come up with. You can use the built-in zip() function. This, when combined with list slicing, results in a pythonic way to pair the values in the required order.
def zipper(a,b):
lst = []
for i in range(1,len(b)+1):
lst+=zip(a,b[i:])
return sorted(lst)
Now simply call zipper on the various rows of data.
>>> a = [2,4,5]
>>> b = [4,7,8,9]
>>> print(zipper(a,a))
[(2, 4), (2, 5), (4, 5)]
>>> print(zipper(b,b))
[(4, 7), (4, 8), (4, 9), (7, 8), (7, 9), (8, 9)]
As a side note, I tried to use list comprehension to make the code shorter. For example, the following code does the same thing as zipper(a):
def zipper(a):
return list(zip(a,a[i:]) for i in range(1,len(a)+1))
However, with zip() returning generator objects in Python 3, the results aren't as "clean" as the output from the version above. I'd have to use next() on each generator object in the list outputted by zipper in order to get the same output, but this is a tedious process. Anyone have suggestions for making the list comprehension work?
(yes, I've searched all around for a solution, and, if did I see it, I wasn't able to relate to my issue. I'm new to Python, sorry!)
I've got a work to do, and it says to me:
"User will input X and Y. Show a sequence from 1 to Y, with only X elements each line."
e.g
2 4 as entrance
1 2
3 4
e.g 2 6
1 2
3 4
5 6
Okay... So, I thought on doing this:
line, final = input().split()
line = int(line)
final = int(final)
List = []
i = 0
total = (final // line)
spot = 0
correction = 0
k = 1
if i != final:
List = list(range(1, final + 1, 1))
i += 1
while k != total:
spot = line * k + correction
correction += 1
k += 1
list.insert(List, spot, '\n')
print(*List)
Ok. So I managed to build my List from 1 to the "final" var.
Also managed to find on which spots (therefore, var "spot") my new line would be created. (Had to use a correction var and some math to reach it, but it's 10/10)
So far, so good.
The only problem is this work is supposed to be delivered on URI Online Judge, and it DEMANDS that my result shows like this:
2 10 as entrance
1 2
3 4
5 6
7 8
9 10
And, using the code I just posted, I get this as a result:
1 2
3 4
5 6
7 8
9 10
Thus, it says my code is wrong. I've tried everything to remove those spaces (I think). Using sys won't work since it only prints one argument. Tried using join (but I could have done it wrong, as I'm new anyway)
Well, I've tried pretty much anything. Hope anyone can help me.
Thanks in advance :)
You have built a list that includes each necessary character, including the linefeed. Therefore, you have a list like this:
[1, 2, '\n', 3, 4, '\n'...]
When you unpack arguments to print(), it puts a separator between each argument, defaulting to a space. So, it prints 1, then a space, then 2, then a space, then a linefeed, then a space... And that is why you have a space at the beginning of each line.
Instead of inserting linefeeds into a list, chunk that list with iter and next:
>>> def chunks(x, y):
... i = iter(range(1, y+1))
... for row in range(y//x):
... print(*(next(i) for _ in range(x)))
... t = tuple(i)
... if t:
... print(*t)
...
>>> chunks(2, 6)
1 2
3 4
5 6
>>> chunks(2, 7)
1 2
3 4
5 6
7
The problem with the approach you're using is a result of a space being printed after each "\n" character in the series. While the idea was quite clever, unfortunately, I think this means you will have to take a different approach from inserting the newline character into the list.
Try this approach: (EDITED)
x, y = input().split()
x, y = int(x), int(y)
for i in range(1, y+1):
if i % x == 0 or i == y:
print(i)
else:
print(i, end=" ")
Output for 3 11
1 2 3
4 5 6
7 8 9
10 11
Output for 2 10
1 2
3 4
5 6
7 8
9 10
Use itertools to take from an iterable in chunks:
>>> import itertools
>>> def print_stuff(x,y):
... it = iter(range(1, y + 1))
... chunk = list(itertools.islice(it,X))
... while chunk:
... print(*chunk)
... chunk = list(itertools.islice(it,X))
...
>>> print_stuff(2,4)
1 2
3 4
>>>
And here:
>>> print_stuff(2,10)
1 2
3 4
5 6
7 8
9 10
>>>
I split user input into two string then convert them into int and comapre if y greater than x by 2 because this is minimum for drawing your sequence
Then i make a list from 1 to y
And iterate over it 2 element for each iteration printing them
x,y=input().split()
if int(y)>int(x)+2:
s=range(1,int(y)+1)
for i in range(0,len(s),2):
print(' '.join(str(d) for d in s[i:i+2]))
result:
1 2
3 4
5 6
7 8
9 10