0

I can list the image files in a directory and they look like this:

['IMG_3842.CR2', 'IMG_3843.CR2', 'IMG_3844.CR2', 'IMG_3846.CR2', 'IMG_3847.CR2', 
'IMG_3848.CR2', 'IMG_3849.CR2', 'IMG_3850.CR2', 'IMG_3851.CR2', 'IMG_3852.CR2', 
'IMG_3855.CR2', 'IMG_3856.CR2', 'IMG_3857.CR2', 'IMG_3858.CR2', 'IMG_3859.CR2']

The file numbers range from 3842 to 3859. However, there are gaps in the numbers. What I need to do is get a list like this as an output:

3842-3844, 3846-3852, 3855-3859

Dhara
  • 6,587
  • 2
  • 31
  • 46

3 Answers3

1

Something like this: [Iteration is straighforward, I just wanted to try it the reduce way ;)]

S = ['IMG_3842.CR2', 'IMG_3843.CR2', 'IMG_3844.CR2', 'IMG_3846.CR2', 'IMG_3847.CR2', 'IMG_3848.CR2', 'IMG_3849.CR2', 'IMG_3850.CR2', 'IMG_3851.CR2', 'IMG_3852.CR2', 'IMG_3855.CR2', 'IMG_3856.CR2', 'IMG_3857.CR2', 'IMG_3858.CR2', 'IMG_3859.CR2', 'IMG_3863.CR2']

l = sorted([int(x[x.index("_")+1:x.index(".")]) for x in S])

def func(l,val):
    if val == l[-1][1]+1:
        l[-1] = (l[-1][0], l[-1][1]+1)
    else:
        l.append((val,val))
    return l

res = reduce(func, l, [(-1,-1)])[1:]
print [str(x[0]) if x[0] == x[1] else "{}-{}".format(x[0],x[1]) for x in res]

OUTPUTS:

['3842-3844', '3846-3852', '3855-3859', '3863']
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104
  • Ok thank you for the reply, that gives me the missing image numbers. But how would I get the list like this: 3842-3844, 3846-3852, 3855-3859. Thanks for the help – Dennis Davis Jun 29 '12 at 16:29
  • @DennisDavis When I read your question again, I realised I did the exact opposite ;). I updated my answer. – UltraInstinct Jun 29 '12 at 16:32
  • That worked well except if my list of files has a single value like this – Dennis Davis Jun 29 '12 at 19:55
  • Here is code: S = ['IMG_3842.CR2', 'IMG_3843.CR2', 'IMG_3844.CR2', 'IMG_3845.CR2', 'IMG_3847.CR2', 'IMG_3849.CR2', 'IMG_3850.CR2', 'IMG_3853.CR2', 'IMG_3856.CR2', 'IMG_3857.CR2', 'IMG_3858.CR2'] l = sorted([int(x[x.index("_")+1:x.index(".")]) for x in S]) def func(l,val): if val == l[-1][1]+1: l[-1] = (l[-1][0], l[-1][1]+1) else: l.append((val,val)) return l print ["%d-%d"%x for x in reduce(func, l, [(-1,-1)])[1:]] – Dennis Davis Jun 29 '12 at 20:20
  • Here is the output: ['3842-3845', '3847-3847', '3849-3850', '3853-3853', '3856-3858'] How can I get it formated like this please? ['3842-3845', '3847', '3849-3850', '3853', '3856-3858'] thank you for the help – Dennis Davis Jun 29 '12 at 20:20
  • sorry, I don't know how to put in the code block for you to see – Dennis Davis Jun 29 '12 at 20:21
  • @DennisDavis I have updated my answer. And to write small chunnks of code in the comments, use backtick ` (usually found above the TAB key) around the code. :) – UltraInstinct Jun 30 '12 at 05:57
  • Thank you very much. I will try the updated answer. I really appreciate your help as I am a real newb at this. I have been asked to create a script at work and that is the last part that I could not figure out. Dennis – Dennis Davis Jun 30 '12 at 20:23
  • @DennisDavis Hope that helps. Once you are done with it, you need to upvote answers that helped you, and accept the most satisfying response. :) – UltraInstinct Jul 01 '12 at 04:58
  • This worked really well and does exactly what I needed. I can't thank you enough for helping me. Dennis – Dennis Davis Jul 04 '12 at 13:57
  • Glad that helped you, and since you are new on Stackoverflow, let me tell you that you need to accept (click green tick mark on left) the answer that worked for you. It also helps future readers. :) – UltraInstinct Jul 04 '12 at 14:14
1

Assuming the list is already ordered, and all items have the same format

l = ['IMG_3842.CR2', 'IMG_3843.CR2', 'IMG_3844.CR2', 'IMG_3846.CR2', 'IMG_3847.CR2', 'IMG_3848.CR2', 'IMG_3849.CR2', 'IMG_3850.CR2', 'IMG_3851.CR2', 'IMG_3852.CR2', 'IMG_3855.CR2', 'IMG_3856.CR2', 'IMG_3857.CR2', 'IMG_3858.CR2', 'IMG_3859.CR2']

numl = [int(x[4:8]) for x in l]

first = numl[0]
result = []

for i in range(len(numl))[1:]:
    if numl[i] != numl[i-1] + 1:
        result.append(str(first) + '-' + str(numl[i-1]))
        first = numl[i]

result.append(str(first) + '-' + str(numl[-1]))

print result

Output:

['3842-3844', '3846-3852', '3855-3859']

xvatar
  • 3,229
  • 17
  • 20
1

Referring to Python splitting list based on missing numbers in a sequence

import glob
from itertools import groupby

def ranges(seq, key=int):
    return [[x[1] for x in g] for k, g in groupby(enumerate(seq), lambda i,x:i-key(x))]

files = list(glob.glob('*.cr2'))
files.sort()

Now you can call

ranges(files, key=lambda s: int(s[4:8]))

and get

[
    ['IMG_3842.CR2',
     'IMG_3843.CR2',
     'IMG_3844.CR2'],
    ['IMG_3846.CR2',
     'IMG_3847.CR2',
     'IMG_3848.CR2',
     'IMG_3849.CR2',
     'IMG_3850.CR2',
     'IMG_3851.CR2',
     'IMG_3852.CR2'],
    ['IMG_3855.CR2',
     'IMG_3856.CR2',
     'IMG_3857.CR2',
     'IMG_3858.CR2',
     'IMG_3859.CR2']
]

Edit:

filenums = [f[4:8] for f in files]
range_strings = ["{}-{}".format(rng[0], rng[-1]) for rng in ranges(filenums)]

gives

['3842-3844', '3846-3852', '3855-3859']
Community
  • 1
  • 1
Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • i can use that for another part of my tool but I have to have them printed like this first: ['3842-3844', '3846-3852', '3855-3859'] thank you for your help – Dennis Davis Jun 29 '12 at 19:49