-1

In R there is the rep function that allows you to repeat a vector, and with the additional argument length.out one is able to specify the length of the final vector/array, e.g.:

> rep(1:3, length.out = 10)
 [1] 1 2 3 1 2 3 1 2 3 1

Is there a similar way in Python to do this? I have found the repeat function in Numpy, but one is only able to specify number of times to repeat.

Georgy
  • 12,464
  • 7
  • 65
  • 73
Helen
  • 533
  • 12
  • 37
  • Also: [Repeat values in array until specific length](https://stackoverflow.com/q/63837217/7851470) – Georgy Sep 18 '20 at 12:26
  • The linked question is about numpy arrays, this one is about python lists. Not a duplicate from my perspective. – paleonix Jun 24 '22 at 17:28

4 Answers4

3

You can by combining itertools cycle and islice methods:

>>> from itertools import islice, cycle
>>> list(islice(cycle([1,2,3]), 10))
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
Lanting
  • 3,060
  • 12
  • 28
  • Thanks! Is there no way of doing this without importing a library? I am trying to transfer from R to Python, and I'm surprised I have to import a library to do this? – Helen Sep 18 '20 at 12:19
  • @Helen https://docs.python.org/3/library/itertools.html is part of The Python Standard Library and comes with python by default. – Lanting Sep 18 '20 at 12:21
  • Ok, thank you very much! Guess I have to read up on what a standard library is. Thanks again :) – Helen Sep 18 '20 at 12:22
2

This should do what you need for any sequences (list, tuple, string, etc) as long as they support + and *, which should be the case for the output to make any sense.

def repeat(seq, length):
    multiple, remainder = divmod(length, len(seq))
    return seq * multiple + seq[:remainder]

>>> repeat([1, 2, 3], 10)
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]

>>> repeat('abc', 10)
'abcabcabca'

>>> repeat([1, 2, 3], 2)
[1, 2]
aviso
  • 2,371
  • 1
  • 14
  • 15
  • 1
    it breaks for `repeat(range(1,4),10)`, though – Lanting Sep 18 '20 at 12:29
  • Because range type is not a sequence, `list(range(1, 4))` will work – aviso Sep 18 '20 at 12:30
  • How is it not a sequence? – Kelly Bundy Sep 18 '20 at 12:32
  • `isinstance(range, collections.abc.Sequence)` – aviso Sep 18 '20 at 12:35
  • 1
    You're doing that wrong. And `isinstance(range(1, 4), collections.abc.Sequence)` says `True`. – Kelly Bundy Sep 18 '20 at 12:46
  • Sorry, just realized that. Yes, they are sequences, technically, but they don't support the * or + operators (`__mul__` and `__add__`) which are listed as common sequence operations in the docs, so I would not consider them fully implemented sequences. Granted, those might be difficult to implement or not make as much sense for range objects. range objects also don't make sense for input here because of that, there are no range objects which repeat, so you couldn't have your output type match your input type. So blowing up makes sense, otherwise you have to guess what the use wants. – aviso Sep 18 '20 at 12:53
  • Hmm, where do the docs say that? Neither the [glossary](https://docs.python.org/3/glossary.html#term-sequence) nor the [`collections.abc.Sequence` doc](https://docs.python.org/3/library/collections.abc.html#collections.abc.Sequence) do. – Kelly Bundy Sep 18 '20 at 12:58
  • https://docs.python.org/3/library/stdtypes.html#common-sequence-operations – aviso Sep 18 '20 at 13:02
  • Well that *explicitly* says that `range` *is* a sequence type. The table rows about `+` and `*` refer to note 7, which says "Some sequence types (such as `range`) [...]". Btw, please notify people when you reply. Or are you trying to have the last word that way? – Kelly Bundy Sep 18 '20 at 13:15
  • Yes, in Python 3 it's a sequence, but not a fully implemented one. Still doesn't address the point it's not valid input on a function like this because the output wouldn't make sense, which is probably what I should have said in the first place. – aviso Sep 18 '20 at 14:28
  • Nah, it's a fully implemented one, those other ones just implement some *extra* stuff. At least according to all those docs, including the part that you showed. And I guess it's confirmed, you omit notifications to have the last (wrong) word. – Kelly Bundy Sep 18 '20 at 14:54
  • Could care less. You should get automatically notified of replies. Updated the text to account for the discussion. – aviso Sep 18 '20 at 15:38
  • How much less? No, I didn't get notified, as there's another commenter here (Lanting). – Kelly Bundy Sep 18 '20 at 21:35
1

You could divide the desired length by the given length, then you know how many full copies you need and how much of a partial copy you need for the remainder.

>>> a = [1, 2, 3]
>>> n = 10

>>> q, r = divmod(n, len(a))
>>> q * a + a[:r]
[1, 2, 3, 1, 2, 3, 1, 2, 3, 1]
Kelly Bundy
  • 23,480
  • 7
  • 29
  • 65
0

Sure thing, Range of 1-4 means that the output will be 1,2,3. n defines the number of times you want to repeat. and length defines the maximum length you want to keep.

n=2
length=5
print((list(range(1,4))*n)[:length])
Yash
  • 1,271
  • 1
  • 7
  • 9
  • I think you misunderstood the question dear friend, I'm sorry somebody downvoted you! Maybe you can try again and help me? :) – Helen Sep 18 '20 at 12:15
  • Yes, that works, but how do you know that n suffices for the length you chose? – Helen Sep 18 '20 at 12:16
  • @Helen It doesn't. It will first create a list according to n and then slice it to the length you want.. I dont know why someone downvoted without even stating the reason. – Yash Sep 18 '20 at 12:16
  • 1
    It was downvoted when it was just something like `(list(range(1,4))*n`, without the slicing, and that was obviously not solving the problem. – Kelly Bundy Sep 18 '20 at 12:21
  • @HeapOverflow ok. I had forgotten to add explanation and was about to edit. But the downvote was pretty instantaneous, – Yash Sep 18 '20 at 12:22