답변:
이 문제에 대한 최상의 해결책은 아닐 것입니다.
indices = 0, 2
somelist = [i for j, i in enumerate(somelist) if j not in indices]
somelist = [ lst[i] for i in xrange(len(lst)) if i not in set(indices) ]
어때?
어떤 이유로 나는 여기에 대답이 마음에 들지 않습니다. 예, 작동하지만 엄밀히 말하면 대부분 목록에서 요소를 삭제하지는 않습니까? (그러나 사본을 만든 다음 원본을 편집 된 사본으로 바꾸십시오).
왜 더 높은 색인을 먼저 삭제하지 않습니까?
이것에 대한 이유가 있습니까? 나는 단지 할 것이다 :
for i in sorted(indices, reverse=True):
del somelist[i]
항목을 뒤로 삭제하지 않으려면 마지막으로 삭제 된 색인보다 큰 색인 값을 줄이거 나 (다른 목록을 가지고 있기 때문에 실제로 동일한 색인을 사용할 수는 없음) 추측해야합니다 목록의 사본 ( '삭제'하지 않고 원본을 편집 된 사본으로 대체)
역순으로 삭제하지 않는 이유가 있습니까?
인접하지 않은 여러 항목을 삭제하는 경우 설명하는 것이 가장 좋습니다 (그렇습니다. 가장 높은 색인에서 시작하십시오).
아이템이 인접한 경우 슬라이스 할당 구문을 사용할 수 있습니다.
a[2:10] = []
del a[2:10]
같은 효과로 말할 수도 있습니다 .
numpy.delete
다음과 같이 사용할 수 있습니다 .
import numpy as np
a = ['a', 'l', 3.14, 42, 'u']
I = [0, 2]
np.delete(a, I).tolist()
# Returns: ['l', '42', 'u']
마지막에 numpy
배열로 끝나는 것이 마음에 들지 않으면를 생략하십시오 .tolist()
. 속도가 상당히 향상되어 확장 성이 뛰어난 솔루션이 될 것입니다. 벤치마킹하지는 않았지만 numpy
작업은 C 또는 Fortran으로 작성된 코드로 컴파일됩니다.
기능으로서 :
def multi_delete(list_, *args):
indexes = sorted(list(args), reverse=True)
for index in indexes:
del list_[index]
return list_
n log (n) 시간 내에 실행 되므로 아직 가장 빠른 올바른 솔루션이되어야합니다.
n log n
? 정말? 나는 del list[index]
O (1) 라고 생각하지 않습니다 .
따라서 한 번에 여러 요소를 삭제하고 싶습니까? 이 경우 삭제할 다음 요소의 위치는 이전에 삭제 된 많은 요소에 의해 오프셋됩니다.
우리의 목표는 인덱스 1, 4 및 7로 미리 계산 된 모든 모음을 삭제하는 것입니다. to_delete 인덱스는 오름차순으로되어 있어야합니다. 그렇지 않으면 작동하지 않습니다.
to_delete = [1, 4, 7]
target = list("hello world")
for offset, index in enumerate(to_delete):
index -= offset
del target[index]
어떤 순서로든 요소를 삭제하려면 더 복잡합니다. IMO, to_delete
에서 빼거나 빼야 할 때를 알아내는 것보다 정렬 이 더 쉬울 수 있습니다 index
.
나는 파이썬의 초보자입니다. 지금은 프로그래밍이 거칠고 지저분하지만, 내 솔루션은 초기 자습서에서 배운 기본 명령의 조합을 사용하는 것이 었습니다.
some_list = [1,2,3,4,5,6,7,8,10]
rem = [0,5,7]
for i in rem:
some_list[i] = '!' # mark for deletion
for i in range(0, some_list.count('!')):
some_list.remove('!') # remove
print some_list
분명히 "삭제 표시"문자를 선택해야하기 때문에 여기에는 한계가 있습니다.
목록의 크기가 확장 될 때의 성능에 관해서는 솔루션이 차선책이라고 확신합니다. 그러나 그것은 간단합니다. 다른 초보자들에게 호소하기를 바랍니다 some_list
. 잘 알려진 형식 (예 : 항상 숫자) 인 간단한 경우에 작동 합니다 ...
다음은 SilentGhost의 원래 답변과 같이 enumerate ()를 사용하여 튜플을 생성하지 않는 대안입니다.
이것은 나에게 더 읽기 쉬운 것 같습니다. 열거 형을 사용하는 습관이 있다면 다르게 느낄 수도 있습니다.주의 사항 : 두 가지 접근 방식의 성능을 테스트하지 않았습니다.
# Returns a new list. "lst" is not modified.
def delete_by_indices(lst, indices):
indices_as_set = set(indices)
return [ lst[i] for i in xrange(len(lst)) if i not in indices_as_set ]
참고 : Python 2.7 구문. Python 3의 경우 xrange
=> range
.
용법:
lst = [ 11*x for x in xrange(10) ]
somelist = delete_by_indices( lst, [0, 4, 5])
somelist :
[11, 22, 33, 66, 77, 88, 99]
--- 보너스 ---
목록에서 여러 값을 삭제하십시오. 즉, 삭제하려는 값이 있습니다.
# Returns a new list. "lst" is not modified.
def delete__by_values(lst, values):
values_as_set = set(values)
return [ x for x in lst if x not in values_as_set ]
용법:
somelist = delete__by_values( lst, [0, 44, 55] )
somelist :
[11, 22, 33, 66, 77, 88, 99]
이것은 이전과 같은 대답이지만 이번에는 삭제할 VALUES를 제공했습니다 [0, 44, 55]
.
[ value for (i, value) in enumerate(lst) if i not in set(indices) ]
. 그러나 값으로 삭제하는 방법도 보여주기 때문에 여기에 답을 남겨 두겠습니다. 더 쉬운 경우이지만 누군가를 도울 수 있습니다.
indices_as_set = set(indices)
, 로 다시 작성 [ value for (i, value) in enumerate(lst) if i not in indices_as_set ]
하여 속도를 높일 것입니다.
delete__by_values()
있습니까?
여기에 요소를 제거하는 또 다른 방법이 있습니다. 또한 목록이 정말 길면 더 빠릅니다.
>>> a = range(10)
>>> remove = [0,4,5]
>>> from collections import deque
>>> deque((list.pop(a, i) for i in sorted(remove, reverse=True)), maxlen=0)
>>> timeit.timeit('[i for j, i in enumerate(a) if j not in remove]', setup='import random;remove=[random.randrange(100000) for i in range(100)]; a = range(100000)', number=1)
0.1704120635986328
>>> timeit.timeit('deque((list.pop(a, i) for i in sorted(remove, reverse=True)), maxlen=0)', setup='from collections import deque;import random;remove=[random.randrange(100000) for i in range(100)]; a = range(100000)', number=1)
0.004853963851928711
이것은 언급되었지만 어떻게 든 실제로 그것을 제대로 얻을 수는 없었습니다.
에에게 O(n)
해결책은 다음과 같습니다
indices = {0, 2}
somelist = [i for j, i in enumerate(somelist) if j not in indices]
이것은 SilentGhost의 버전 과 거의 비슷하지만 두 개의 중괄호를 추가합니다.
O(n)
걸리는 조회를 계산하는 경우 에는 그렇지 않습니다 log(len(indices))
.
j not in indices
는 O(1)
입니다.
j not in indices
여전히 조회가 필요합니다 O(log(len(indices)))
. 2- 요소 집합의 조회는 다음과 같은 자격이있는 것에 동의하지만 O(1)
일반적인 경우에는 다음과 같습니다 O(log(N))
. 어느 쪽이든 O(N log(N))
여전히 이길 수 O(N^2)
있습니다.
j not in indices
는 O(1)
심각합니다.
기술적으로 대답은 아니요입니다. 같은 시간에 두 개체를 삭제할 수 없습니다. 그러나 한 줄의 아름다운 파이썬에서 두 개의 객체를 삭제할 수 있습니다.
del (foo['bar'],foo['baz'])
recusrively 삭제 foo['bar']
한 다음foo['baz']
노브를 돌리기 쉽게하는 여러 가지 솔루션을 비교하는 방법을 원했습니다.
먼저 내 데이터를 생성했습니다.
import random
N = 16 * 1024
x = range(N)
random.shuffle(x)
y = random.sample(range(N), N / 10)
그런 다음 내 기능을 정의했습니다.
def list_set(value_list, index_list):
index_list = set(index_list)
result = [value for index, value in enumerate(value_list) if index not in index_list]
return result
def list_del(value_list, index_list):
for index in sorted(index_list, reverse=True):
del(value_list[index])
def list_pop(value_list, index_list):
for index in sorted(index_list, reverse=True):
value_list.pop(index)
그런 다음 timeit
솔루션을 비교하는 데 사용 했습니다.
import timeit
from collections import OrderedDict
M = 1000
setup = 'from __main__ import x, y, list_set, list_del, list_pop'
statement_dict = OrderedDict([
('overhead', 'a = x[:]'),
('set', 'a = x[:]; list_set(a, y)'),
('del', 'a = x[:]; list_del(a, y)'),
('pop', 'a = x[:]; list_pop(a, y)'),
])
overhead = None
result_dict = OrderedDict()
for name, statement in statement_dict.iteritems():
result = timeit.timeit(statement, number=M, setup=setup)
if overhead is None:
overhead = result
else:
result = result - overhead
result_dict[name] = result
for name, result in result_dict.iteritems():
print "%s = %7.3f" % (name, result)
산출
set = 1.711
del = 3.450
pop = 3.618
따라서 지수가있는 발전기가 set
승자가되었습니다. 그리고 del
약간 빠릅니다 pop
.
실제로 두 가지 방법을 생각할 수 있습니다.
목록을 슬라이스하십시오 (이것은 1, 3 및 8 번째 요소를 삭제합니다)
somelist = somelist [1 : 2] + somelist [3 : 7] + somelist [8 :]
한 번에 하나씩 그 위치에서 수행하십시오.
somelist.pop (2) somelist.pop (0)
목록이 아닌 dict에서 그렇게 할 수 있습니다. 목록에서 요소는 순서대로 있습니다. dict에서 그들은 인덱스에만 의존합니다.
간단한 코드는 다음을 수행 하여 설명합니다 .
>>> lst = ['a','b','c']
>>> dct = {0: 'a', 1: 'b', 2:'c'}
>>> lst[0]
'a'
>>> dct[0]
'a'
>>> del lst[0]
>>> del dct[0]
>>> lst[0]
'b'
>>> dct[0]
Traceback (most recent call last):
File "<pyshell#19>", line 1, in <module>
dct[0]
KeyError: 0
>>> dct[1]
'b'
>>> lst[1]
'c'
dict에서 목록을 "변환"하는 방법은 다음과 같습니다.
>>> dct = {}
>>> for i in xrange(0,len(lst)): dct[i] = lst[i]
그 반대는 다음과 같습니다.
lst = [dct[i] for i in sorted(dct.keys())]
어쨌든 나는 당신이 말한 것처럼 더 높은 색인에서 삭제를 시작하는 것이 낫다고 생각합니다.
@sth 의 주석을 일반화합니다 . 구현이 그 모든 클래스에서 항목 삭제, abc.MutableSequence , 그리고에 list
특히,을 통해 이루어집니다 __delitem__
마술 방법. 이 방법은와 비슷하게 작동합니다 __getitem__
. 즉, 정수 또는 슬라이스를 사용할 수 있습니다. 예를 들면 다음과 같습니다.
class MyList(list):
def __delitem__(self, item):
if isinstance(item, slice):
for i in range(*item.indices(len(self))):
self[i] = 'null'
else:
self[item] = 'null'
l = MyList(range(10))
print(l)
del l[5:8]
print(l)
출력됩니다
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[0, 1, 2, 3, 4, 'null', 'null', 'null', 8, 9]
이 중 하나는 어떻습니까 (파이썬을 처음 접했지만 괜찮아 보입니다 ).
ocean_basin = ['a', 'Atlantic', 'Pacific', 'Indian', 'a', 'a', 'a']
for i in range(1, (ocean_basin.count('a') + 1)):
ocean_basin.remove('a')
print(ocean_basin)
[ '대서양', '태평양', '인도']
ob = ['a', 'b', 4, 5,'Atlantic', 'Pacific', 'Indian', 'a', 'a', 4, 'a']
remove = ('a', 'b', 4, 5)
ob = [i for i in ob if i not in (remove)]
print(ob)
[ '대서양', '태평양', '인도']
지금까지 제안 된 답변 중에 삭제 수행하지 않습니다 장소에서 삭제할 인덱스의 임의의 수의리스트의 길이에 O (N)에서를, 그래서 여기 내 버전입니다 :
def multi_delete(the_list, indices):
assert type(indices) in {set, frozenset}, "indices must be a set or frozenset"
offset = 0
for i in range(len(the_list)):
if i in indices:
offset += 1
elif offset:
the_list[i - offset] = the_list[i]
if offset:
del the_list[-offset:]
# Example:
a = [0, 1, 2, 3, 4, 5, 6, 7]
multi_delete(a, {1, 2, 4, 6, 7})
print(a) # prints [0, 3, 5]
list_diff
첫 번째 목록의 원래 순서를 유지하면서 단순히 두 목록을 입력으로 가져 와서 그 차이를 반환 하는 함수에 모두 넣었습니다 .
def list_diff(list_a, list_b, verbose=False):
# returns a difference of list_a and list_b,
# preserving the original order, unlike set-based solutions
# get indices of elements to be excluded from list_a
excl_ind = [i for i, x in enumerate(list_a) if x in list_b]
if verbose:
print(excl_ind)
# filter out the excluded indices, producing a new list
new_list = [i for i in list_a if list_a.index(i) not in excl_ind]
if verbose:
print(new_list)
return(new_list)
샘플 사용법 :
my_list = ['a', 'b', 'c', 'd', 'e', 'f', 'woof']
# index = [0, 3, 6]
# define excluded names list
excl_names_list = ['woof', 'c']
list_diff(my_list, excl_names_list)
>> ['a', 'b', 'd', 'e', 'f']