我正在尝试向列表添加值,但仅限于尚未添加的值。
是否有命令执行此操作或有没有办法测试列表中是否存在值?
谢谢!
答案 0 :(得分:8)
我需要做同样的事情。 我想从列表中删除元素然后再添加它。如果元素不在列表中,redis将返回0,因此没有错误
lrem mylist 0 myitem
rpush mylist myitem
答案 1 :(得分:4)
正如Tommaso Barbugli所提到的,如果您只需要唯一值,则应使用集合而不是列表。 see REDIS documentation SADD
redis> SADD myset "Hello"
(integer) 1
redis> SADD myset "World"
(integer) 1
redis> SADD myset "World"
(integer) 0
redis> SMEMBERS myset
1) "World"
2) "Hello"
如果要检查集合中是否存在值,可以使用SISMEMBER
redis> SADD myset "one"
(integer) 1
redis> SISMEMBER myset "one"
(integer) 1
redis> SISMEMBER myset "two"
(integer) 0
答案 2 :(得分:2)
看起来你需要一套或一组排序。
集合具有O(1)成员资格测试和强制唯一性。
答案 3 :(得分:1)
使用redis中的hexists
hexists命令在集合中可以使用此功能。
答案 4 :(得分:1)
检查列表以查看其中是否存在成员是O(n),这对于大型列表来说可能会非常昂贵,并且绝对不是理想的。也就是说,其他人似乎都在为您提供替代方案。我只会告诉你如何做你要做的事情,并假设你有充分的理由按照你的方式去做。我将在Python中执行此操作,假设您与Redis有r
的连接,一些名为some_list
的列表和一些要添加的新项目new_item
:
lst = r.lrange(list_name, -float('Inf'), float('Inf'))
if new_item not in lst:
r.rpush(list_name, new_item)
答案 5 :(得分:1)
如果您不能使用SET(如果要实现某些阻止POP / PUSH列表的功能),则可以使用简单的脚本:
script load 'local exists = false; for idx=1, redis.call("LLEN",KEYS[1]) do if (redis.call("LINDEX", KEYS[1], idx) == ARGV[1]) then exists = true; break; end end; if (not exists) then redis.call("RPUSH", KEYS[1], ARGV[1]) end; return not exists or 0'
这将返回您添加的脚本的SHA代码。
然后致电:
evalsha 3e31bb17571f819bea95ca5eb5747a373c575ad9 1 test-list myval
其中
3e31bb17571f819bea95ca5eb5747a373c575ad9
(您添加的脚本的SHA代码)1
—是参数的数量(此功能为1不变)test-list
-您的列表名称myval
-您需要添加的值如果添加了新项目,则返回1;如果已经在列表中,则返回0。
答案 6 :(得分:0)
在添加到任务工作者队列时遇到了此问题,因为我想避免添加许多重复的任务。使用Redis集(很多人都建议)会很好,但是Redis集没有像BRPOPLPUSH这样的“阻塞弹出”,因此它们不适用于任务队列。
因此,这是我略微不理想的解决方案(在Python中):
def pushOnlyNewItemsToList(redis, list_name, items):
""" Adds only the items that aren't already in the list.
Though if run simultaneously in multiple threads, there's still a tiny chance of adding duplicate items.
O(n) on the size of the list."""
existing_items = set(redis.lrange(list_name,0,-1))
new_items = set(items).difference(existing_items)
if new_items:
redis.lpush(list_name, *new_items)
请注意文档字符串中的警告。
如果您需要真正保证没有重复,则可以选择在Redis管道中运行LREM和LPUSH,如0xAffe的回答。这种方法会减少网络流量,但不利于重新排序列表。如果您不在乎列表顺序,这可能是最好的一般答案。