How to get a different output? - python

I am new to python programming. I was trying to write a program to find how many 9s are present in the list.enter image description here
seq = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
n = 0
t = []
y = len(seq)
for x in range (0, y-1):
if seq[x] == 9:
n += 1
t.append(x+1)
else: continue
print (n, "numbers of 9s are present at", t, "position" )'
output: 2 numbers of 9s are present at [5, 9] position
How i have write the program to get the output as "2 numbers of 9s are present at 5 and 9 position".

You can use the list comprehension. enumerate return the element (num) of list and the index of element (idx) and if the element (num) is equal to 9 then the positions list will contain the idx as a string. The indexing starts from 1 (not 0) (start=1). You can get the number of 9s with len(positions) and you can join the element with " and ".join(positions).
Code:
seq = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
positions = [str(idx) for idx, num in enumerate(seq, start=1) if num == 9]
print("{} numbers of 9s are present at {} positions".format(len(positions), " and ".join(positions)))
Output:
>>> python3 test.py
2 numbers of 9s are present at 5 and 9 positions
I guess it is the most elegant way to solve your issue.

your_list = [4,5,6,7,9,6,7,9]
indexes = []
for i, num in enumerate(your_list, start=1):
if num == 9:
indexes.append(i)
def output_list(str_list):
last_value = str_list[-1]
first_indexes = str_list[:-1]
first_indexes_str = ", ".join(first_indexes)
if len(first_indexes) == 0:
return f'{len(indexes)} numbers of 9s are present at {last_value} position'
return f'{len(indexes)} numbers of 9s are present at {first_indexes_str} and {last_value} position'
print(output_list(indexes))
first empty list of the index list.
loop over the list and get the index by using (enumerate).
if the num is nine append to the indexes list.
after that print by using the f'...' and print how much find and where.
and add the function that parses the data as wanted

Well, first make a for loop in your list, taking each element, then compare this element to 9 to see if it's a 9 or not. compt variable will count "9" encounters.
compt = 0
seq = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
for k in seq:
if(k == 9):
compt += 1
print(compt)
If you also want the index / position of nines founds, then do the same, looping on index, and keep an index list :
compt = 0
indexlist = []
seq = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
for k in range(0, len(seq)):
if(seq[k] == 9):
compt += 1
indexlist.append(k)
print(str(compt) + " nines founds, in following positions : " + str(indexlist))

You can use locate present in more_itertools module
from more_itertools import locate
arr = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
indices = list(locate(arr, lambda a: a==9))
You can add +1 to each element in the indices to get the position

seq = [1, 2, 3, 4, 9, 6, 8, 13, 9, 12, 19]
positions = [i + 1 for i in range(len(seq)) if seq[i] == 9]
print(f"{len(positions)} numbers of 9s are present at {positions} position")

Related

Flip half of a list and append it to itself

Im trying to flip half of the elements inside of a list and then spend it onto itself, for example,
if I pass the list [1, 8, 7, 2, 9, 18, 12, 0] into it, I should get [1, 0, 7, 18, 9, 2, 12, 8] out, here is my current code
def flip_half(list):
for i in range(0,len(list)):
if i % 2 != 0:
listflip = list[i]
print(listflip)
return list
You can directly assign slices in python. So if you can determine the slice you want to assign from and to, you can directly change the elements. This assign from every other element in reverse l[::-2] to every other element starting with the second: l[1::2] :
l = [1, 8, 7, 2, 9, 18, 12, 0]
l[1::2] = l[::-2]
print(l)
#[1, 0, 7, 18, 9, 2, 12, 8]
If you wanted to do it in a loop:
def flip_half(list):
out = []
for i in range(0,len(list)):
if i % 2 != 0:
out.append(list[-i])
else:
out.append(list[i])
return out
print(flip_half([1, 8, 7, 2, 9, 18, 12, 0]))
If you need that elements with odd indexes has reverse order then one of next solutions (l - is your list):
Slices
l[1::2] = l[1::2][::-1]
List comprehension
l = [l[i] if i % 2 == 0 else l[-(i + len(l)%2)] for i in range(len(l))]
Function
def flip_half(lst):
res= []
for i in range(len(lst)):
if i % 2 != 0:
res.append(lst[-(i + len(lst) % 2)])
else:
res.append(lst[i])
return res
l = flip_half(l)
Generator function
def flip_half(lst):
for i in range(len(lst)):
if i % 2 != 0:
yield lst[-(i + len(lst) % 2)]
else:
yield lst[i]
l = list(flip_half(l))

Can anyone help me to optimize this piece of code?

I want to store even number and odd number in a separate list. But, here I am facing a unique problem. I am able to store it in sets but not in lists. Is there a way wherein I can store these in a List without repetition.
I have tried this in Jupyter notebook
list_loop=[1,2,3,4,5,6,7,8,9,10,11,12,13,1,4,1,51,6,17,]
for i in list_loop:
if i % 2 == 0 :
list_even = list_even + [i]
else:
list_odd = list_odd + [i]
print(set(list_even))
print(set(list_odd))
Expected output:
[2,4,6,8,10,12]
[1,3,5,7,9,11,13,17,51]
Define list_odd and list_even as lists and don't convert them to sets before printing. Note that you can use list comprehension to fill list_odd and list_even:
list_odd = []
list_even = []
list_loop=[1,2,3,4,5,6,7,8,9,10,11,12,13,1,4,1,51,6,17,]
list_odd = [elem for elem in list_loop if elem % 2 != 0]
list_even = [elem for elem in list_loop if elem % 2 == 0]
print(list_even)
print(list_odd)
Output:
[2, 4, 6, 8, 10, 12, 4, 6]
[1, 3, 5, 7, 9, 11, 13, 1, 1, 51, 17]
Edit: for uniqueness, turn list_loop into a set:
list_loop=set([1,2,3,4,5,6,7,8,9,10,11,12,13,1,4,1,51,6,17,])
Output:
[2, 4, 6, 8, 10, 12]
[1, 3, 5, 7, 9, 11, 13, 17, 51]
Use a comprehension
>>> list_loop=[1,2,3,4,5,6,7,8,9,10,11,12,13,1,4,1,51,6,17,]
>>> print(list(set(_ for _ in list_loop if _ % 2)))
[1, 3, 5, 7, 9, 11, 13, 17, 51]
Similarly for even numbers.
There are a couple of ways you could do this. You could use the OrderedDict in the collections library, or you could just sort the set and get a list,
...
print(sorted(set(list_even)))
print(sorted(set(list_odd)))
Also, I would personally create those lists using a set comprehension
list_even = sorted({x for x in list_loop if x % 2 == 0})
list_odd = sorted({x for x in list_loop if x % 2 == 1})
You can solve this using a list comprehension with a filter condition - but you then iterate your list twice.
By using a simple for loop you only need to touch any number once at it will conserve the original order - what putting your numbers through a set might not do - order in a set is not guaranteed:
Keep a set of seen numbers, only add anything if your current number was not yet seen.
list_loop = [1,2,3,4,5,6,7,8,9,10,11,12,13,1,4,1,51,6,17,]
list_even = []
list_odd = []
seen = set()
trick = [list_even, list_odd] # even list is at index 0, odd list at index 1
for i in list_loop:
if i in seen:
continue
else:
seen.add(i)
# the trick eliminates the need for an if-clause
trick[i%2].append(i) # you use i%2 to get either the even or odd index
print(list_even)
print(list_odd)
Output:
[2, 4, 6, 8, 10, 12]
[1, 3, 5, 7, 9, 11, 13, 51, 17]
You can apply the list function to your set object in order to
convert it to a list.
list_from_set = list(set(list_even))
>>> print(list_from_set)
[2, 4, 6, 8, 10, 12]

How to print out certain elements of a list in python?

So I have a list li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] and I only want to print out elements that are a part of an arithmetic sequence 6n - 5 (1st, 7th and 13th).
How can I do that if I have a list with n elements?
You could simply say
print([x for x in li if x % 6 == 1])
or, alternatively, if you just want the sequence and don't want to bother about creating li in the first place,
print([6*n-5 for n in range(1, (13+5)//6+1)])
Use the code:
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
new=[]
for i in li:
if int((i+5)/6)==((i+5)/6):
#You can also use
#if ((i+5)/6).is_integer():
new.append(i)
I tried to make it as easy as possible.
Hope it helps :)
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
for n in range(1,len(li)+1): #choose n such that it is length of the list since it cant have more values than the number of values in the list.
for i in li:
if (6*n - 5) == i:
print(i)
Hope this helps
Thanks
Michael
From what I understand, you want the elements whose positions are generated by the sequence. Hence, you want elements from an array of length n whose index is from the sequence function 6x-5.
NOTE: I am assuming you are using 1-based indexing, which means, when you say 1st element in your list, you intend to get 1 and not 2.
n = 13
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
# generate the sequence till n
seq = []
x = 1
while 6*x-5 <= n:
seq.append(6*x-5)
x += 1
# Print the elements from the sequence:
for idx in seq:
print(li[idx-1])
# If you want to store it in another list:
li2 = [li[idx-1] for idx in seq]
Below is a more generic and efficient way for above code:
n = 13
li = list(range(1, n+1)) # More easy to write
# More efficient way is to create a generator function
def get_seq(n):
x = 1
while 6*x-5 <= n:
yield 6*x-5
x += 1
# Get the generator object
seq = get_seq(n)
# Print the elements from the sequence:
for idx in seq:
print(li[idx-1])
# Want to store it in another list:
seq = get_seq(n) # Don't forget to get a new generator object.
li2 = [li[idx-1] for idx in seq]
Output for both snippets:
1
7
13
Hope the answer helps, and remove confusion for others as well ;)
You can simply generate the sequence for any n.
for example:
n = 10
print([ 6*x - 5 for x in range(1,n)])
output:
[1, 7, 13, 19, 25, 31, 37, 43, 49]
>>> [Finished in 0.2s]
But if you just want to filter your existing list li:
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
print([ x for x in li if x % 6 == 1 ])
output:
[1, 7, 13]
>>>
[Finished in 0.3s]
li[1] is 2, li[7] is 8 and the element with the index 13 is out of range.
li = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
for num, i in enumerate(li):
if ((num + 5)/6).is_integer():
print(i)
# 2
# 8
If you want to start with the index 1 add start=1 to the enumerate() function.
for num, i in enumerate(li, start=1):
if ((num + 5)/6).is_integer():
print(i)
# 1
# 7
# 13

Multiples of 3 and 5

I am trying to write a program that takes an input number T(number of test cases), and then asks for the numbers N.
This is my code:
T = int(raw_input())
L = [int(raw_input()) for i in range(T)]
L1 = []
for i in range(0,L[i]):
if (i%3 == 0 or i%5 ==0):
L1.append(i)
print L1
Input: 2 10 20
Output: [0, 3, 5, 6, 9, 10, 12, 15, 18]
I would like the output to be of the following format:
[[0, 3, 5, 6, 9], [0, 3, 5, 6, 9, 10, 12, 15, 18]]
Here [0, 3, 5, 6, 9] is the list that has elements with both multiples of 3 and 5 for number 10
[0, 3, 5, 6, 9, 10, 12, 15, 18] is the list that has elements with both multiples of 3 and 5 for number 20
I am new to python. kindly let me know how I should proceed on this.
The following will produce a list of lists containing all the multiples of 3 and 5 that are less than the given number.
L = [10,20]
L1 = []
for i in L:
L2 = [] # initialize a new list
for j in range(i):
if not (j%3 and j%5): # use falsy values and DeMorgan's Law
L2.append(j) # append to this list
if L2: # use this if you don't want to keep empty lists
L1.append(L2)
>>> L1
[[0, 3, 5, 6, 9], [0, 3, 5, 6, 9, 10, 12, 15, 18]]
I think what you want is splitting a list by input values. Hope it helps
num = int(raw_input())
upperBounds= [int(raw_input()) for i in range(num)]
res= []
for upperBound in upperBounds:
res.append([i for i in range(0,upperBound) if not (i % 3 and i % 5)])
output:
2
10
20
[[0, 3, 5, 6, 9], [0, 3, 5, 6, 9, 10, 12, 15, 18]]
This can be easily done by applying appropriate logic:
if the element at index 0 we have to iterate from 0 to that element
else we have to iterate form L[index-1] to L[index]
T = int(raw_input())
L = [int(raw_input()) for i in range(T)]
L1 = []
for j in xrange(len(L)):
temp = []
get = 0 if not j else L[j-1]
# if j==0:
# get = 0
# else:
# get = L[j-1]
for i in range(get, L[j]):
if (i%3 == 0 or i%5 ==0):
temp.append(i)
L1.append(temp)
print L1
>>> [[0, 3, 5, 6, 9], [10, 12, 15, 18]]
Or a more Pythonic and compacted version may look like:
T = int(raw_input())
L = [int(raw_input()) for i in range(T)]
L1 = []
for j in xrange(len(L)):
get = 0 if not j else L[j-1]
L1.append([i for i in range(get, L[j]) if (i%3 == 0 or i%5 ==0)])
print L1
You can simply generate a list of multiples with range(l,u,s) with l the lower bounds, u the upper bound and d the step.
Now if we want to generate multiples of i for a given range, we can use the following function:
def multiples(factor, lower, upper) :
return set(range(lower+(factor-lower)%factor,upper,factor))
We thus manipulate the lower bound as lower+(factor-lower)%factor in order to search - in constant time - the first multiple that is greater than or equal to lower.
Next we need to multiples of 3 and 5:
def multiples35(lower, upper):
return sorted(list(multiples(3,lower,upper)|multiples(5,lower,upper)))
Now we only need to iterate over the list of values and generate the list of multiples for each two numbers:
def func(B):
return [multiples35(0,upper) for upper in B]
Or as full code:
import sets
def multiples(factor, lower, upper) :
return set(range(lower+(factor-lower)%factor,upper,factor))
def multiples35(lower, upper):
return sorted(list(multiples(3,lower,upper)|multiples(5,lower,upper)))
def func(B):
return [multiples35(0,upper) for upper in B]
The main function reads then:
T = int(raw_input())
B = [int(raw_input()) for i in range(T)]
print func(B)

Detecting consecutive integers in a list [duplicate]

This question already has answers here:
Identify groups of consecutive numbers in a list
(19 answers)
Closed 4 years ago.
I have a list containing data as such:
[1, 2, 3, 4, 7, 8, 10, 11, 12, 13, 14]
I'd like to print out the ranges of consecutive integers:
1-4, 7-8, 10-14
Is there a built-in/fast/efficient way of doing this?
From the docs:
>>> from itertools import groupby
>>> from operator import itemgetter
>>> data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
>>> for k, g in groupby(enumerate(data), lambda (i, x): i-x):
... print map(itemgetter(1), g)
...
[1]
[4, 5, 6]
[10]
[15, 16, 17, 18]
[22]
[25, 26, 27, 28]
You can adapt this fairly easily to get a printed set of ranges.
A short solution that works without additional imports. It accepts any iterable, sorts unsorted inputs, and removes duplicate items:
def ranges(nums):
nums = sorted(set(nums))
gaps = [[s, e] for s, e in zip(nums, nums[1:]) if s+1 < e]
edges = iter(nums[:1] + sum(gaps, []) + nums[-1:])
return list(zip(edges, edges))
Example:
>>> ranges([2, 3, 4, 7, 8, 9, 15])
[(2, 4), (7, 9), (15, 15)]
>>> ranges([-1, 0, 1, 2, 3, 12, 13, 15, 100])
[(-1, 3), (12, 13), (15, 15), (100, 100)]
>>> ranges(range(100))
[(0, 99)]
>>> ranges([0])
[(0, 0)]
>>> ranges([])
[]
This is the same as #dansalmo's solution which I found amazing, albeit a bit hard to read and apply (as it's not given as a function).
Note that it could easily be modified to spit out "traditional" open ranges [start, end), by e.g. altering the return statement:
return [(s, e+1) for s, e in zip(edges, edges)]
This will print exactly as you specified:
>>> nums = [1, 2, 3, 4, 7, 8, 10, 11, 12, 13, 14]
>>> ranges = sum((list(t) for t in zip(nums, nums[1:]) if t[0]+1 != t[1]), [])
>>> iranges = iter(nums[0:1] + ranges + nums[-1:])
>>> print ', '.join([str(n) + '-' + str(next(iranges)) for n in iranges])
1-4, 7-8, 10-14
If the list has any single number ranges, they would be shown as n-n:
>>> nums = [1, 2, 3, 4, 5, 7, 8, 9, 12, 15, 16, 17, 18]
>>> ranges = sum((list(t) for t in zip(nums, nums[1:]) if t[0]+1 != t[1]), [])
>>> iranges = iter(nums[0:1] + ranges + nums[-1:])
>>> print ', '.join([str(n) + '-' + str(next(iranges)) for n in iranges])
1-5, 7-9, 12-12, 15-18
Built-In: No, as far as I'm aware.
You have to run through the array. Start off with putting the first value in a variable and print it, then as long as you keep hitting the next number do nothing but remember the last number in another variable. If the next number is not in line, check the last number remembered versus the first number. If it's the same, do nothing. If it's different, print "-" and the last number. Then put the current value in the first variable and start over.
At the end of the array you run the same routine as if you had hit a number out of line.
I could have written the code, of course, but I don't want to spoil your homework :-)
I had a similar problem and am using the following for a sorted list. It outputs a dictionary with ranges of values listed in a dictionary. The keys separate each run of consecutive numbers and are also the running total of non-sequential items between numbers in sequence.
Your list gives me an output of {0: [1, 4], 1: [7, 8], 2: [10, 14]}
def series_dictf(index_list):
from collections import defaultdict
series_dict = defaultdict(list)
sequence_dict = dict()
list_len = len(index_list)
series_interrupts = 0
for i in range(list_len):
if i == (list_len - 1):
break
position_a = index_list[i]
position_b = index_list[i + 1]
if position_b == (position_a + 1):
sequence_dict[position_a] = (series_interrupts)
sequence_dict[position_b] = (series_interrupts)
if position_b != (position_a + 1):
series_interrupts += 1
for position, series in sequence_dict.items():
series_dict[series].append(position)
for series, position in series_dict.items():
series_dict[series] = [position[0], position[-1]]
return series_dict
Using set operation, the following algorithm can be executed
def get_consecutive_integer_series(integer_list):
integer_list = sorted(integer_list)
start_item = integer_list[0]
end_item = integer_list[-1]
a = set(integer_list) # Set a
b = range(start_item, end_item+1)
# Pick items that are not in range.
c = set(b) - a # Set operation b-a
li = []
start = 0
for i in sorted(c):
end = b.index(i) # Get end point of the list slicing
li.append(b[start:end]) # Slice list using values
start = end + 1 # Increment the start point for next slicing
li.append(b[start:]) # Add the last series
for sliced_list in li:
if not sliced_list:
# list is empty
continue
if len(sliced_list) == 1:
# If only one item found in list
yield sliced_list[0]
else:
yield "{0}-{1}".format(sliced_list[0], sliced_list[-1])
a = [1, 2, 3, 6, 7, 8, 4, 14, 15, 21]
for series in get_consecutive_integer_series(a):
print series
Output for the above list "a"
1-4
6-8
14-15
21
Here is another basic solution without using any module, which is good for interview, generally in the interview they asked without using any modules:
#!/usr/bin/python
def split_list(n):
"""will return the list index"""
return [(x+1) for x,y in zip(n, n[1:]) if y-x != 1]
def get_sub_list(my_list):
"""will split the list base on the index"""
my_index = split_list(my_list)
output = list()
prev = 0
for index in my_index:
new_list = [ x for x in my_list[prev:] if x < index]
output.append(new_list)
prev += len(new_list)
output.append([ x for x in my_list[prev:]])
return output
my_list = [1, 3, 4, 7, 8, 10, 11, 13, 14]
print get_sub_list(my_list)
Output:
[[1], [3, 4], [7, 8], [10, 11], [13, 14]]
You can use collections library which has a class called Counter. Counter can come in handy if trying to poll the no of distinct elements in any iterable
from collections import Counter
data = [ 1, 4,5,6, 10, 15,16,17,18, 22, 25,26,27,28]
cnt=Counter(data)
print(cnt)
the output for this looks like
Counter({1: 1, 4: 1, 5: 1, 6: 1, 10: 1, 15: 1, 16: 1, 17: 1, 18: 1, 22: 1, 25: 1, 26: 1, 27: 1, 28: 1})
which just like any other dictionary can be polled for key values

Categories

Resources