检查项目是否已经在具有引用相等性的列表中
Check if item is already in a list with referential equality
我想检查某个项目是否已经在具有引用相等性而非结构相等性的列表中。
为清楚起见:
referential equality between 2 items is checked with
item1 is item2
structural equality is checked with item1 == item2
检查一个项目是否已经在列表中的结构相等很容易像这样完成:
item in list
所以我正在寻找具有引用相等性的等效行。如果不遍历列表中的每个项目,这可能吗?
需要如何实施的示例(仅供说明):
def get_all_items_in_list(items):
all_items = []
for item in items:
if not item in all_items: # replace with referential equality here
all_items.append(item)
return all_items
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items)) # should print [(1, []), (1, [])] but prints [(1, [])]
试试这个,
a=10
b=20
c=30
l=[id(a),id(b),id(c)]
id(a) in l
因此,根据 "is" python's operator,它检查对象的 identity
,这可以通过 id()
函数实现(进一步滚动以获取解决方案).
# as you did
a = (1, [])
b = (1, []) # two different objects
print(a is b)
print(id(a), id(b))
>>> False
>>> 2076884715144 2076884729224
# Now let's try making the second object the same
c = (2, [])
d = c #objects are the same
print(c is d)
print(id(c), id(d))
>>> True
>>> 2076899815240 2076899815240
解决方案:
下面的想法是获取另一个列表中与原始列表位置相同的所有ids()。检查项目是否在列表中时,您将检查身份是否已经在列表中。
def get_ids_items_in_list(items):
""" Get the identity of the objects in same order as list"""
items_ids = []
for item in items:
items_ids.append(id(item))
return items_ids
def get_all_items_in_list(items_list):
# get our ids
items_ids = get_ids_items_in_list(items_list)
all_items = []
all_items_id = []
# Loops over the ids but using enumerate to get positions
for idx, item in enumerate(items_ids):
if not item in all_items_id:
all_items_id.append(item)
# if id is in list, append object according to position
all_items.append(items_list[idx])
return all_items
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items))
>>> False
>>> [(1, []), (1, [])]
关于该主题的更多信息:
# another thing to notice is that a simple copy()
# will return the same object
from copy import copy
e = (3, [])
f = copy(e)
print(e is f)
print(id(e), id(f))
>>> True
>>> 2076884710600 2076884710600
# but a deepcopy will change the identity
from copy import deepcopy
g = (4, [])
h = deepcopy(g)
print(g is h)
print(id(g), id(h))
>>> False
>>> 2076884714120 2076884715016
您可以使用由项目 id
键入的中间 dict
作为标识集:
def get_all_items_in_list(items):
return {id(it): it for it in items}.values()
# arrange
a = (1, [])
b = (1, [])
items = [a, a, b]
# act
result = list(get_all_items_in_list(items))
# assert
print(result[0] is a)
print(result[1] is b)
如果没有 一些 循环,你将无法做到这一点。 in
的 python 中没有检查身份的等效运算符。一个简短的解决方案可能如下所示:
l = [1,2,3]
l2 = [[1, 2, 3], [4, 5, 6]]
l3 = [[1, 2, 3], [4, 5, 6], l]
any(l is sub for sub in l2)
# false
any(l is sub for sub in l3)
# True
它仍然循环,但如果找到真值,它会提前退出。
如果您真的需要为此使用运算符,您可以子类化UserList
并覆盖__contains__()
。这将改变 in
:
的行为
from collections import UserList
class identList(UserList):
def __contains__(self, other):
return any(other is sub for sub in self)
l = [1,2,3]
l2 = identList([[1, 2, 3], [4, 5, 6]])
l3 = identList([[1, 2, 3], [4, 5, 6], l])
l in l2
# False
l in l3
# True
#With minimal changes in existing code snippet
def get_all_items_in_list(items):
all_items = {}
for item in items:
if not id(item) in all_items: # replace with referential equality here
all_items[id(item)] = item
return all_items.values()
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items))
输出:
False
dict_values([(1, []), (1, [])])
我想检查某个项目是否已经在具有引用相等性而非结构相等性的列表中。
为清楚起见:
referential equality between 2 items is checked with
item1 is item2
structural equality is checked with
item1 == item2
检查一个项目是否已经在列表中的结构相等很容易像这样完成:
item in list
所以我正在寻找具有引用相等性的等效行。如果不遍历列表中的每个项目,这可能吗?
需要如何实施的示例(仅供说明):
def get_all_items_in_list(items):
all_items = []
for item in items:
if not item in all_items: # replace with referential equality here
all_items.append(item)
return all_items
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items)) # should print [(1, []), (1, [])] but prints [(1, [])]
试试这个,
a=10
b=20
c=30
l=[id(a),id(b),id(c)]
id(a) in l
因此,根据 "is" python's operator,它检查对象的 identity
,这可以通过 id()
函数实现(进一步滚动以获取解决方案).
# as you did
a = (1, [])
b = (1, []) # two different objects
print(a is b)
print(id(a), id(b))
>>> False
>>> 2076884715144 2076884729224
# Now let's try making the second object the same
c = (2, [])
d = c #objects are the same
print(c is d)
print(id(c), id(d))
>>> True
>>> 2076899815240 2076899815240
解决方案:
下面的想法是获取另一个列表中与原始列表位置相同的所有ids()。检查项目是否在列表中时,您将检查身份是否已经在列表中。
def get_ids_items_in_list(items):
""" Get the identity of the objects in same order as list"""
items_ids = []
for item in items:
items_ids.append(id(item))
return items_ids
def get_all_items_in_list(items_list):
# get our ids
items_ids = get_ids_items_in_list(items_list)
all_items = []
all_items_id = []
# Loops over the ids but using enumerate to get positions
for idx, item in enumerate(items_ids):
if not item in all_items_id:
all_items_id.append(item)
# if id is in list, append object according to position
all_items.append(items_list[idx])
return all_items
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items))
>>> False
>>> [(1, []), (1, [])]
关于该主题的更多信息:
# another thing to notice is that a simple copy()
# will return the same object
from copy import copy
e = (3, [])
f = copy(e)
print(e is f)
print(id(e), id(f))
>>> True
>>> 2076884710600 2076884710600
# but a deepcopy will change the identity
from copy import deepcopy
g = (4, [])
h = deepcopy(g)
print(g is h)
print(id(g), id(h))
>>> False
>>> 2076884714120 2076884715016
您可以使用由项目 id
键入的中间 dict
作为标识集:
def get_all_items_in_list(items):
return {id(it): it for it in items}.values()
# arrange
a = (1, [])
b = (1, [])
items = [a, a, b]
# act
result = list(get_all_items_in_list(items))
# assert
print(result[0] is a)
print(result[1] is b)
如果没有 一些 循环,你将无法做到这一点。 in
的 python 中没有检查身份的等效运算符。一个简短的解决方案可能如下所示:
l = [1,2,3]
l2 = [[1, 2, 3], [4, 5, 6]]
l3 = [[1, 2, 3], [4, 5, 6], l]
any(l is sub for sub in l2)
# false
any(l is sub for sub in l3)
# True
它仍然循环,但如果找到真值,它会提前退出。
如果您真的需要为此使用运算符,您可以子类化UserList
并覆盖__contains__()
。这将改变 in
:
from collections import UserList
class identList(UserList):
def __contains__(self, other):
return any(other is sub for sub in self)
l = [1,2,3]
l2 = identList([[1, 2, 3], [4, 5, 6]])
l3 = identList([[1, 2, 3], [4, 5, 6], l])
l in l2
# False
l in l3
# True
#With minimal changes in existing code snippet
def get_all_items_in_list(items):
all_items = {}
for item in items:
if not id(item) in all_items: # replace with referential equality here
all_items[id(item)] = item
return all_items.values()
# setup
a = (1, [])
b = (1, [])
print(a is b) # prints False
items = [a, a, b]
print(get_all_items_in_list(items))
输出:
False
dict_values([(1, []), (1, [])])