Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scanning a list

Tags:

python

I need to scan a list in Python. I'm able to load it from file and do simple operation, but I was trying to do the following:

L = [1,2,3,4,5,6,7,8]

Starting from the first element I want to produce the following output:

1
  2,3,4,5,6,7,8
  3,4,5,6,7,8
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
2
  3,4,5,6,7,8
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
3
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
4
  5,6,7,8
  6,7,8
  7,8
  8

and so on.

I was trying something like this:

fo = open(sys.argv[1], 'r')
L = fo.readlines()
for i in range(len(L)):
    print str(L[i])
    for j in range(len(L)-1-i):
        print '...' + str(L[i+j+1])

Could you help me ?

like image 749
Denise Mendez Gomez Avatar asked Aug 01 '13 09:08

Denise Mendez Gomez


2 Answers

How's this? Nice and simple to read:

>>> for i, j in enumerate(L):
...     print L[i]
...     temp = map(str, L[j:])
...     while temp:
...             print ' ', ','.join(temp)
...             temp = temp[1:]
... 
1
  2,3,4,5,6,7,8
  3,4,5,6,7,8
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
2
  3,4,5,6,7,8
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
3
  4,5,6,7,8
  5,6,7,8
  6,7,8
  7,8
  8
...

while temp means while the list temp is not empty. We have to call map(str, L[j:]) here because the list is full of integers (and thus the str.join method would not work)


Just another note, it's more pythonic to use a with statement when working with files:

with open(sys.argv[1], 'r') as fo:
    L = fo.readlines()
like image 124
TerryA Avatar answered Oct 04 '22 01:10

TerryA


While Haidro answer produces desired output, I should say that this is pretty inefficient algorithm to do the task provided.

quick analysis:

for i, j in enumerate(L):          # loop number 1, for i from 1 to N
    print L[i]
    temp = map(str, L[j:])         
    while temp:                    # nested loop number 2, for j from i to N
        print ' ', ','.join(temp)  # nested loop number 3, for k from j to N
        temp = temp[1:]

it's too much work for such a simple task. I think it could be made much simplier and faster, joining string just once and then print substrings (as DCM mentioned in comments, to be able to print arbitrary numbers we should precalculate positions of the elements in the string):

s = ",".join(map(str, l))                  # creating string
p = [len(str(x)) + 1 for x in l]           # calculating length of each element
p = [sum(p[:i]) for i in range(len(p))]    # calculating positions with rolling total
for i in range(len(l)):                    # loop number 1
    print l[i]
    for j in range(i + 1, len(l)):         # nested loop number 2
        print ' ', s[p[j]:]

Here's quick profile of execution times (I've create function worker1 with Haidro code and worker2 with mine). You can see how the grows time of execution when you increase input length N:

>>> from timeit import timeit

>>> timeit("worker1(l)", "from testSO import worker1, l", number=10)
0.0016222212978796024
>>> timeit("worker1(l*10)", "from testSO import worker1, l", number=10)
0.33153371422580324
>>> timeit("worker1(l*100)", "from testSO import worker1, l", number=10)
163.25908817145972

It grows like O(N^3)

>>> timeit("worker2(l)", "from testSO import worker2, l", number=10)
0.0006974355000011201
>>> timeit("worker2(l*10)", "from testSO import worker2, l", number=10)
0.03448374103493279
>>> timeit("worker2(l*100)", "from testSO import worker2, l", number=10)
4.446190059150922

This one grows like O(N^2)

It's not that I think that original question looks like performance critical task, but I think it would be nice if people see why algorithm provided could be slower than they expecting.

like image 40
Roman Pekar Avatar answered Oct 03 '22 23:10

Roman Pekar