Redis diff between two lists?

2019-09-07 00:35发布

问题:

As I know sDiff works only with sets. But how can i get diff between indexed lists?

....
$Redis->lPush("KEY1", "Value1");
$Redis->lPush("KEY1", "Value2");
$Redis->lPush("KEY1", "Value3");

$Redis->lPush("KEY2", "Value1");
$Redis->lPush("KEY2", "Value3");
$Redis->lPush("KEY2", "Value4");

$Redis->sDiff("KEY1", "KEY2");
....

回答1:

There is no built-in command for that - your options are either pull the two lists and perform the comparison (for diff) in the client, or write a Lua script that is run with the EVAL command to perform it server-side. Here's an example for such a script:

--[[ 
LDIFF key [key ...]
Returns the elements in the first list key that are also present in all other
keys.
]]--

-- A utility function that converts an array to a table
local function a2t(a)
  local t = {}
  for i, v in ipairs(a) do
    t[v] = true
  end
  return t
end

-- A utility function that converts a table to an array
local function t2a(t)
  local a = {}
  for k, _ in pairs(t) do
    a[#a+1] = k
  end
  return a
end

-- main
local key = table.remove(KEYS,1)
local elems = a2t(redis.call('LRANGE', key, 0, -1))

-- iterate remaining keys
while #KEYS > 0 do
  key = table.remove(KEYS,1)
  local check = a2t(redis.call('LRANGE', key, 0, -1))
  -- check each element in the current key for existence in the first key
  for k, _ in pairs(elems) do
    if check[k] then
      elems[k] = nil
    end
  end
end

-- convert the table to an array and reply
return t2a(elems)

Running this with redis-cli looks like this:

$ redis-cli LPUSH key1 value1 value2 value3
(integer) 3
$ redis-cli LPUSH key2 value1 value3 value4
(integer) 3
$ redis-cli --eval ldiff.lua key1 key2
1) "value2"


回答2:

Redis doesn't have in-built support for finding list differences. But there is a workaround. By seeing the syntax of your code, I assume you are working on php. PHP array_diff() is to rescue. Following steps should work.

$a1 = $Redis->lPush("KEY1",0,-1)
$a2 = $Redis->lPush("KEY2",0,-1)
diff = array_diff($a1,$a2)

This approach can be translated to any other programming language.

p.s. If the lists are huge, make sure you get the difference in batch, instead of loading all the items at once.



标签: php redis