angularNoob
angularNoob

Reputation: 39

Removing non-image files from a list

Suppose I want to remove all list items that do not stand for jpg or png files.

arr = ['doc01.pdf', 'doc02.pdf', 'img01.PNG', 'img02.jpg']
for i in arr:
    if i.lower().find("jpg") == -1 and i.lower().find("jpeg") == -1 and i.lower().find("png") == -1:
        arr.remove(i)
print(arr) 

Why am I getting this:

['doc02.pdf', 'img02.jpg']

I thought all 3 comparisons should become true for the pdfs and this they should be removed.

Upvotes: 0

Views: 532

Answers (3)

zyeek
zyeek

Reputation: 1287

Like @scott-hunter said you don't want to modify the list you are looping over.

In that case, you ideally would make a copy that you would feed into the loop, use index-based for loop or better you get functional with it. Use a filter.

filter(lambda f: f.lower().endswith(('.jpg', '.jpeg', '.png')), arr)
// input: arr = ['doc01.pdf', 'doc02.pdf', 'img01.PNG', 'img02.jpg']
// output: ['img01.PNG', 'img02.jpg']

Edit:

Neat, @HSK's suggestion of itertools.filterfalse to remove.

list(itertools.filterfalse(lambda f: f.lower().endswith(('.jpg', '.jpeg', '.png')), arr))
// input: arr = ['doc01.pdf', 'doc02.pdf', 'img01.PNG', 'img02.jpg']
// output: ['doc01.pdf', 'doc02.pdf']

Upvotes: 1

user10703542
user10703542

Reputation:

no_img = [ _ for _ in arr if not (_.lower().endswith("img") or _.lower().endswith("jpg")) ]

Upvotes: 1

Slawomir Dziuba
Slawomir Dziuba

Reputation: 1325

The question is at a very basic level so some explanations can be useful.

One of the ways to solve:

arr = ['do.jpg.c01.pdf', 'pngdoc02.pdf', 'img01.PNG', 'img02.jpg']
ar=[]
for i in arr:
    j=i.lower()
    if j[-4:] == '.jpg' \
       or j[-4:] == '.png' \
       or j[-5:] == '.jpeg':
        ar.append(i)

print(ar)

Explanation:

  1. j=i.lower() is calculated only once for each loop run,
  2. Breaking the line with the \ character further improves readability
  3. 'or' causes the condition to be calculated only to the first hit,
    meanwhile 'and' forces the calculation of all three conditions in each loop.
    Therefore, the order of the conditions is important
  4. find() with arguments without a dot (ex: 'jpg') would have hit all elements of the arr list,find after adding a dot (ex: '.jpg') would have gone wrong first element.

    String slices solve this problem

Upvotes: 1

Related Questions