Python: How to generate a range skipping every 4th number?

range python
python range reverse
python range float
python range step
range python 3
write a python program to split a list every nth element
python integer range
python range list

I need to create a range skipping over every 4th number, starting from 5. For example, if the range a is from 1-20, then the numbers 5,9,13,17 will be excluded.

a = [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

What I tried is creating a regular range, and then a second range consisting the numbers I want to skip, and then remove the second range from the first one.

a = list(range(1,21))
b = list(range(5,21,4))
for x in b:
   if x in a:
      a.remove(x)

This works, but not for a very large range. Is there a more efficient way to do it?

Solution:

For efficiency, I would recommend using a generator expression like this:

r = (x for x in range(1,21) if x not in range(5,21,4))

or, equivalently, and without needing to write the upper bound twice:

r = (x for x in range(1,21) if x == 1 or x % 4 != 1)

You can use this generator as you would use a normal sequence (list/tuple)*, and convert the generator to a list with list() if you absolutely need to.

Justification:

The advantage of this approach is that it does not require storing all of the items in memory, so you can make the upper bound arbitrarily large without any performance problems.


*(Sort of-there are caveats, as mentioned by the commenters below. e.g. if you want fast membership checks, you would be better off just using the two ranges separately)

Python: How to generate a range skipping every 4th number?, I need to create a range skipping over every 4th number, starting from Possible duplicate of Skip over a value in the range function in python import itertools m, n = 5, 10 for i in itertools.chain(range(m), range(m + 1, n)): print(i) # skips m = 5 As an aside, you woudn't want to use (*range(m), *range(m + 1, n)) even though it works because it will expand the iterables into a tuple and this is memory inefficient.

Use a set and another list comprehension:

a = range(1, 21)
b = set(range(5, 21, 4))

[i for i in a if i not in b]
# [1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

You could remove the set from the second range, but I am finding this is slower than set inclusion checking:

Functions

def chris(m):
  a = range(1, m)
  b = set(range(5, m, 4))
  return [i for i in a if i not in b]

def chris2(m):
  a = range(1, m)
  b = range(5, m, 4)
  return [i for i in a if i not in b]


def ollin(m):
  return list(x for x in range(1,m) if x not in range(5,m,4))

def ollin2(m):
  return list(x for x in range(1,m) if x == 1 or x % 4 != 1)

def smac(m):
  return [v for i, v in enumerate(range(1,m)) if i == 0 or i % 4 != 0]

Setup

from timeit import timeit

import pandas as pd
import matplotlib.pyplot as plt

res = pd.DataFrame(
       index=['chris', 'chris2', 'ollin', 'ollin2', 'smac'],
       columns=[10, 50, 100, 500, 1000, 5000, 10000],
       dtype=float
)

for f in res.index: 
    for c in res.columns:
        stmt = '{}(c)'.format(f)
        setp = 'from __main__ import c, {}'.format(f)
        res.at[f, c] = timeit(stmt, setp, number=50)

ax = res.div(res.min()).T.plot(loglog=True) 
ax.set_xlabel("N"); 
ax.set_ylabel("time (relative)");

plt.show()

Python range() Function Explained with Examples, Python range() function generates a list of numbers between the given start integer Python range() example Get numbers from range 0 to 6 0, 1, 2, 3, 4, 5, Next, In every subsequent iteration of for loop, the value of i incremented sequentially. If you are not using Python 2 you can skip this comparison. Python 3’s range uses the generator. Python 3’s range() will produce value when for loop iteration asked for it. i.e., it The range() doesn’t produce all numbers at once. Python range() function returns an immutable sequence object of integers, so its possible to convert range() output to python list.

You can use this list comprehension:

>>> print ([v for i, v in enumerate(range(1,21)) if i == 0 or i % 4 != 0])
[1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

Python Slicing - Adam Short, Every major programming language has it; those familiar square If you say alist​[::4] you're saying after the first element, skip 3, and then take the next. It's the Get a list of numbers with index divisble by n list(range(500))[::n]  Generate random number within a given range in Python Random integer: 7 Random integer: 22 Random integer: 180 Note: You cannot use float value randrange() . It will raise a ValueError: non-integer arg 1 for randrange() if you used values other than an integer.

If we consider numpy

import numpy as np 
a=np.arange(1,21)
a[np.logical_or(a%4!=1,a==1)]
Out[209]: array([ 1,  2,  3,  4,  6,  7,  8, 10, 11, 12, 14, 15, 16, 18, 19, 20])

Python: Split a list every Nth element, Write a Python program to split a list every Nth element. 'm', 'n'] def list_slice(S, step): return [S[i::step] for i in range(step)] print(list_slice(C,3)). Create an empty Numpy Array of given length or shape & data type in Python How to save Numpy Array to a CSV File using numpy.savetxt() in Python numpy.amin() | Find minimum value in Numpy Array and it's index

Writing your own generator function could be useful:

def weird_range():
   for i in range(1, 21):
      if i < 5 or i % 4 != 1:
         yield i

>>> list(weird_range())
[1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

This will let you do all manner of bizarre sequences.


Alternate is to create your own range object:

class WeirdRange:
   def __contains__(self, val):
      return val < 5 or val % 4 != 1

>>> list(_ for _ in range(1,21) if _ in WeirdRange())
[1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

Or you can create your own Iterator:

class WeirdIterator:

   def __init__(self):
      self._idx = 0

   def __iter__(self):
      return self

   def __next__(self):
      self._idx += 1
      if self._idx >= 5  and  self._idx % 4 == 1:
         self._idx += 1
      if self._idx > 20:
         raise StopIteration()
      return self._idx

>>> list(WeirdIterator())
[1, 2, 3, 4, 6, 7, 8, 10, 11, 12, 14, 15, 16, 18, 19, 20]

Python, Skip to content Given a list of numbers, Your task is to remove and print every third number from a list of numbers until the The first third element encountered is 3, after 3 we start the count from 4 for the next third element which is 2. last_page Python | Generate random numbers within a given range and store in a list. Check out the code below: import random for x in range(10): print random.randint(1,21)*5, print. Basically this code will generate a random number between 1 and 20, and then multiply that number by 5. So not only will every number printed be a multiple of 5, but the highest number that can be printed is 100 (20*5=100).

3.3. While Statements, 3, 10, 8+2=10 No test here. 4, print 10. 2, 10 < 9 is false, skip loop Try it: Make up a range function call to generate the list of temperatures printed in the tea from an integer n will eventually reach 1, for every starting integer n greater than 1. start: Starting number of the sequence. stop: Generate numbers up to, but not including this number. step: Difference between each number in the sequence. Note that: All parameters must be integers. All parameters can be positive or negative. range() (and Python in general

Functional Programming HOWTO, Other languages are multi-paradigm languages that support several different As you work on a functional-style program, you'll write a number of functions with Python sequence type, such as strings, will automatically support creation of an for every element, 2) selecting a subset of elements that meet some condition. You can assign this generator to a variable in order to use it. When you call special methods on the generator, such as next (), the code within the function is executed up to yield. When the Python yield statement is hit, the program suspends function execution and returns the yielded value to the caller.

4.7. The range Function, It turns out that generating lists with a specific number of integers is a very So to repeat something four times, a good Python programmer would do this: D. Range should generate a sequence using every 10th number between the start  Approach The index of the list starts from 0 and the first third element will be at position 2. Traverse till the list becomes empty and each time find the index of the next third element and print its corresponding value. After printing reduce the length of the list. # Python program to remove to every third.

Comments
  • Possible duplicate of Skip over a value in the range function in python
  • @RushabhMehta Not much of a duplicate.
  • ranges only support start, stop, step, by definition. Which parts of the range API do you need to keep? sized? O(1) membership? O(1) memory? reversed? slicable?
  • A generator is different from a range object, though. ranges are sized (len) and support O(1) membership test.
  • Upvote for the second one, I actually find that more flexible, And understandable, but that may just be my warped mind :-)
  • No need for b = set(range(5, 21, 4)), range objects have constant-time membership testing for integer
  • I'm getting slower timings (even including the overhead to create the set) if I just use range(5, 21, 4)
  • Are you on Python 3? How are you timing it? In any event, depending on various things, it will be slower or faster, but both should be constant time
  • I'll post my timings
  • @juanpa.arrivillaga I confirm: the set is twice as fast as the range.