7

我正在尝试向列表中添加一个值,但前提是它尚未添加。

是否有执行此操作的命令,或者是否有办法测试列表中是否存在值?

谢谢!

4

7 回答 7

10

我也需要这样做。我想从列表中删除元素,然后再次添加。如果元素不在列表中,redis会返回0,所以没有错误

lrem mylist 0 myitem
rpush mylist myitem 
于 2015-05-20T09:21:28.607 回答
9

正如 Tommaso Barbugli 提到的,如果您只需要唯一值,则应该使用集合而不是列表。 请参阅 REDIS 文档

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
于 2016-02-25T21:30:17.523 回答
2

看起来您需要一个集合或排序集合。

集合具有 O(1) 成员资格测试和强制唯一性。

于 2013-05-18T09:50:39.177 回答
2

如果您不能使用 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。

于 2019-04-15T12:46:35.870 回答
1

在 redis中使用hexistshexists命令设置了此类功能。

于 2013-05-18T12:17:47.357 回答
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)
于 2013-05-18T20:05:06.203 回答
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 的回答所示。这种方法会减少网络流量,但有重新排序列表的缺点。如果您不关心列表顺序,这可能是最好的一般答案。

于 2018-11-18T21:24:23.610 回答