我想要交叉多个集合(2个或更多)。要交叉的集合的数量作为ARGV从命令行传递。正在从命令行传递集合数。所以redis.call()函数中的参数数量是不确定的。
如何使用redis.call()
脚本中的Lua
功能执行此操作。
但是,我写了一个类似的脚本:
setIntersected = redis.call(ARGV[1], ARGV[2])
setIntersected = redis.call("sinter", tostring(setIntersected), set[i])
上述算法的代码是:
local noOfArgs = KEYS[1] -- storing the number of arguments that will get passed from cli
--[[
run a loop noOfArgs time and initialize table elements, since we don't know the number of sets to be intersected so we will use Table (arrays)
--]]
local setsTable = {}
for i = 1, noOfArgs, 1 do
setsTable[i] = tostring(ARGV[i])
end
-- now find intersection
local intersectedVal = redis.call("sinter", setsTable[1], setsTable[2]) -- finding first intersection because atleast we will have two sets
local new_updated_set = ""
for i = 3, noOfArgs, 1 do
new_updated_set = tostring(intersectedVal)
intersectedVal = redis.call("sinter", new_updated_set, setsTable[i])
end
return intersectedVal
当我使用命令行传递两个集时,此脚本正常工作。
EG:
redic-cli --eval scriptfile.lua 2 , points:Above20 points:Above30
output:-
1) "playerid:1"
2) "playerid:2"
3) "playerid:7"
设置points:Above20
和points:Above30
的位置。这次它不会经历从i = 3开始的for循环。
但是当我传递3组时,我总是得到输出:
(空列表或设置)
所以我写的循环有一些问题需要找到集合的交集。
我哪里错了?是否有任何优化的方法可以直接找到多个集合的交集?
答案 0 :(得分:1)
您可能正在寻找的是难以捉摸的unpack()
Lua command,这相当于所谓的" Splat"运算符用其他语言。
在您的代码中,使用以下内容:
angular.module('app.case.controller', [])
.controller('CaseController', function($rootScope, $scope, $state, $stateParams, $filter, casesFactory, $ionicActionSheet, $ionicModal, $ionicTabsDelegate, $ionicLoading, ConnectivityMonitor) {
/// Other non related code
// location map - refactor into a factory
$scope.mapStatus = {};
function initMap () {
var pos = { 'lat': 52.6136149, 'lng': -1.1936672 };
var latLng = new google.maps.LatLng(pos.lat, pos.lng);
var mapOptions = {
center: latLng,
zoom: 15,
mapTypeId: google.maps.MapTypeId.ROADMAP,
fullscreenControl: false,
mapTypeControl: false
};
$scope.map = new google.maps.Map(document.getElementById('map'), mapOptions);
google.maps.event.trigger(map, 'resize');
//Wait until the map is loaded
google.maps.event.addListenerOnce($scope.map, 'idle', function () {
enableMap();
console.log('map loaded');
var marker = new google.maps.Marker({
map: $scope.map,
animation: google.maps.Animation.DROP,
position: latLng
});
google.maps.event.trigger(map, 'resize');
$scope.map.setCenter(latLng);
});
}
function loadGoogleMaps () {
$scope.mapStatus.loading = true;
// This function will be called once the SDK has been loaded
window.mapInit = function(){
initMap();
};
// Create a script element to insert into the page
var script = document.createElement('script');
script.type = 'text/javascript';
script.id = 'googleMaps';
script.src = 'https://maps.googleapis.com/maps/api/js?key=XXX&callback=mapInit';
document.body.appendChild(script);
}
function enableMap () {
$scope.mapStatus.loading = false;
$scope.mapStatus.offline = false;
}
function disableMap () {
$scope.mapStatus.offline = true;
}
function checkLoaded () {
if (typeof google == 'undefined"' || typeof google.maps == 'undefined') {
loadGoogleMaps();
} else {
enableMap();
}
}
function addConnectivityListeners () {
if (ionic.Platform.isWebView()) {
// Check if the map is already loaded when the user comes online, if not, load it
$rootScope.$on('$cordovaNetwork:online', function(event, networkState) {
checkLoaded();
});
// Disable the map when the user goes offline
$rootScope.$on('$cordovaNetwork:offline', function(event, networkState) {
disableMap();
});
} else {
//Same as above but for when we are not running on a device
window.addEventListener("online", function(e) {
checkLoaded();
}, false);
window.addEventListener("offline", function(e) {
disableMap();
}, false);
}
}
function showMap () {
console.log('showMap() called');
if (typeof google == 'undefined' || typeof google.maps == 'undefined') {
console.warn("Google Maps SDK needs to be loaded");
disableMap();
if (ConnectivityMonitor.isOnline()){
loadGoogleMaps();
}
}
else {
if (ConnectivityMonitor.isOnline()){
initMap();
enableMap();
} else {
disableMap();
}
}
addConnectivityListeners();
}
$scope.initMap = function () {
showMap();
};
也就是说,local intersectedVal = redis.call("sinter", unpack(setsTable))
是可变参数,可以接受多个键作为参数。除非你的脚本除了只有集成之外还要做一些事情,否则你最好更好地使用它。