简体   繁体   中英

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.

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']

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM