下面就是小编给大家带来的Redis中实现查找某个值的范围(共含10篇),希望能帮助到大家!同时,但愿您也能像本文投稿人“YohiYoke”一样,积极向本站投稿分享好文章。
这篇文章主要介绍了Redis中实现查找某个值的范围,本文的题引来了Redis作者Salvatore Sanfilippo(@antirez)的回答,比较经典,需要的朋友可以参考下
本文来自Redis在Google Group上的一个问题,有一位同学发贴求助,说要解决如下的一个问题:他有一个IP范围对应地址的列表,现在需要给出一个IP的情况下,迅速的查找到这个IP在哪个范围,也就是要判断此IP的所有地,这个问题引来了Redis作者Salvatore Sanfilippo(@antirez)的回答。解答如下:
例如有下面两个范围,10-20和30-40
代码如下:
A_start 10, A_end 20
B_start 30, B_end 40
我们将这两个范围的起始位置存在Redis的Sorted Sets数据结构中,基本范围起始值作为score,范围名加start和end为其value值:
代码如下:
redis 127.0.0.1:6379> zadd ranges 10 A_start
(integer) 1
redis 127.0.0.1:6379> zadd ranges 20 A_end
(integer) 1
redis 127.0.0.1:6379> zadd ranges 30 B_start
(integer) 1
redis 127.0.0.1:6379> zadd ranges 40 B_end
(integer) 1
这样数据在插入Sorted Sets后,相当于是将这些起始位置按顺序排列好了,
现在我需要查找15这个值在哪一个范围中,只需要进行如下的zrangbyscore查找:
代码如下:
redis 127.0.0.1:6379> zrangebyscore ranges (15 +inf LIMIT 0 1
1) “A_end”
这个命令的意思是在Sorted Sets中查找大于15的第一个值。(+inf在Redis中表示正无穷大,15前面的括号表示>15而非>=15)
查找的结果是A_end,由于所有值是按顺序排列的,所以可以判定15是在A_start到A_end区间上,也就是说15是在A这个范围里。至此大功告成。
当然,如果你查找到的是一个start,比如咱们用25,执行下面的命令
代码如下:
redis 127.0.0.1:6379> zrangebyscore ranges (25 +inf LIMIT 0 1
1) “B_start”
返回结果表明其下一个节点是一个start节点,也就是说25这个值不处在任何start和end之间,不属于任何范围。
当然,这个例子仅适用于类似上面的IP范围查找的案例,因为这些值范围之间没有重合。如果是有重合的情况,这个问题本身也就变成了一个一对多的问题。好吧,如果真的是有重合的范围,我们又当如何解决呢?欢迎读者同学你来挑战。
这里的session机制很简单,用户登录之后,给用户生成一个session,包含用户的唯一编号ID,过期时间expires,以及用户的用户的sessionID,
创建了session之后,将session存放到redis数据库中,现在也只是测试了可以存放数据,并没有进行redis的进一步操作,今后将对redis进行集群操作,虽然小,但是一定要五脏俱全,会写两个类,一个专门用来写,针对主库,然后另一个专门用来读,针对从库。
这需要一个key值与redis从库的连接地址相关联,因为当存在多个key值时,读取是随机的,但是想想,又觉得没有必要,因为主库对从库是完全同步的,就是主库的数据会拷贝完整的一份到从库,先这样想着吧。
redis主要是用到了redis这个模块,模块很多的方法,现在只记录一下用到的:
/** * @description 存储hash结构的数据,同时设置数据的过期时间 * @param {string} 键的名称 * @param {json} 对应的值 * @returns {undefined} */exports.hmset = function (key, json, expires) { try { console.log(“--hmset function begin--”); client.hmset(key, json); if (expires) {client.expire(key,expires); } else {client.expire(key,60 * 30); } } catch (err) { console.log(“lalalla:”+err); }}存值的时候要注意参数的格式,注意redis的错误提示,可以很快的定位问题
还有就是注意异步的特点,比如这里,虽然页面的代码在redis操作之后,但是页面重跳转之后,redis的操作才执行了,
页面跳转之后设置cache保存sessionID,然后当页面跳转的时候,通过读取redis看看sessionID是否存在,来判断用户信息是否过期,没有的话,就更新一下redis的过期时间,因为redis中设置了过期时间,所以sessionID不存在的话,就跳转用户到登录页面
........
Excel2003中怎么查找重复值 下面我们来讲解解决办法,有需要的朋友可参考参考,
打开microsoft office excel 2003版本。这里需要处理的是一份关于学校信息的文档。观察发现有一些学校信息存在重复,并且学校信息在排序上也暂无规律。
首先,为了我们在查找到重复值之后,更好得编辑或删除这些重复值,这里需要将这些学校信息进行排序。选中需要排序的列A,点击菜单栏-数据-排序。在弹出的排序窗口中,保持默认值,点击确定。结果如下图4所示。
选择需要查找重复值的区域,
这里我选择从A2开始下拉选中所有学校信息。点击菜单栏-格式-条件格式。弹出条件格式对话框。如图所示。
拉动条件格式窗口左端条件1(1)的下拉框,选择公式。在后面的公式输入行中输入=COUNTIF(A:A,A2)>1(注:英文半角输入状态)。
将光标转移到下方的按钮“格式”。在弹出的单元格格式窗口中设置当满足=COUNTIF(A:A,A2)>1时,重复值的代用格式。在这里我将重复值格式设置为红色常规。返回条件格式窗口,点击确定。最终的显示结果如下图。
作者: 字体:[增加 减小] 类型:
这篇文章主要介绍了redis数据库查找key在内存中的位置的方法,需要的朋友可以参考下
一、预先需要了解的知识
1、redis 中的每一个数据库,都由一个 redisDb 的结构存储,其中,redisDb.id 存储着 redis 数据库以整数表示的号码。redisDb.dict 存储着该库所有的键值对数据。redisDb.expires 保存着每一个键的过期时间。
2、当redis 服务器初始化时,会预先分配 16 个数据库(该数量可以通过配置文件配置),所有数据库保存到结构 redisServer 的一个成员 redisServer.db 数组中。当我们选择数据库 select number 时,程序直接通过 redisServer.db[number] 来切换数据库。有时候当程序需要知道自己是在哪个数据库时,直接读取 redisDb.id 即可。
3、既然我们知道一个数据库的所有键值都存储在redisDb.dict中,那么我们要知道如果找到key的位置,就有必要了解一下dict 的结构了:
代码如下:
typedef struct dict {
// 特定于类型的处理函数
dictType *type;
// 类型处理函数的私有数据
void *privdata;
// 哈希表(2个)
dictht ht[2];
// 记录 rehash 进度的标志,值为-1 表示 rehash 未进行
int rehashidx;
// 当前正在运作的安全迭代器数量
int iterators;
} dict;
由上述的结构可以看出,redis 的字典使用哈希表作为其底层实现,
dict 类型使用的两个指向哈希表的指针,其中 0 号哈希表(ht[0])主要用于存储数据库的所有键值,而1号哈希表主要用于程序对 0 号哈希表进行 rehash 时使用,rehash 一般是在添加新值时会触发,这里不做过多的赘述。所以redis 中查找一个key,其实就是对进行该dict 结构中的 ht[0] 进行查找操作。
4、既然是哈希,那么我们知道就会有哈希碰撞,那么当多个键哈希之后为同一个值怎么办呢?redis采取链表的方式来存储多个哈希碰撞的键。也就是说,当根据key的哈希值找到该列表后,如果列表的长度大于1,那么我们需要遍历该链表来找到我们所查找的key。当然,一般情况下链表长度都为是1,所以时间复杂度可看作o(1)。
二、当redis 拿到一个key 时,如果找到该key的位置。
了解了上述知识之后,我们就可以来分析redis如果在内存找到一个key了。
1、当拿到一个key后, redis 先判断当前库的0号哈希表是否为空,即:if (dict->ht[0].size == 0)。如果为true直接返回NULL。
2、判断该0号哈希表是否需要rehash,因为如果在进行rehash,那么两个表中者有可能存储该key。如果正在进行rehash,将调用一次_dictRehashStep方法,_dictRehashStep 用于对数据库字典、以及哈希键的字典进行被动 rehash,这里不作赘述。
3、计算哈希表,根据当前字典与key进行哈希值的计算。
4、根据哈希值与当前字典计算哈希表的索引值。
5、根据索引值在哈希表中取出链表,遍历该链表找到key的位置。一般情况,该链表长度为1。
6、当 ht[0] 查找完了之后,再进行了次rehash判断,如果未在rehashing,则直接结束,否则对ht[1]重复345步骤。
到此我们就找到了key在内存的中位置了。
这篇文章主要介绍了Lua检测数组(tabble)中是否包含某个值以及lua 判断一个字符是否存在某个数组两个方法,需要的朋友可以参考下
一、检测数组中是否包含某个值
-- 遍历数组function IsInTable(value, tbl)for k,v in ipairs(tbl) do if v == value then return true; endendreturn false;end
二、lua 判断一个字符是否存在某个数组
判断字符b,是否存在于数组list中
function in_array(b,list) if not list then return false end if list thenfor k, v in pairs(list) do if v.tableName ==b then return true endend end end
作者: 字体:[增加 减小] 类型:
这篇文章主要介绍了Flex中TitleWindow传值思路及实现,需要的朋友可以参考下
1、设计思路
(1)新建一个DataGrid,在其中最后一列加入三个按钮:新增、修改和删除;
(2)点击新增按钮,可以将表格新增一行;
(3)单击“修改”按钮,可以修改表格中该行的一些属性;
(4)单击“删除”按钮,会将表格中该行删除,
2、实现步骤
(1)新建一个应用程序,DataGrid.mxml
DataGrid.mxml:
代码如下:
xmlns:s=“library://ns.adobe.com/flex/spark”
xmlns:mx=“library://ns.adobe.com/flex/mx” minWidth=“955” minHeight=“600”>
import mx.collections.ArrayCollection;
[Bindable]
//表格数据源绑定
private var grid:ArrayCollection = new ArrayCollection([
{number:“010101”,name:“张三”,sex:“男”,age:“19”},
{number:“2014010102”,name:“李思”,sex:“女”,age:“20”},
{number:“2014010103”,name:“蔡华”,sex:“男”,age:“21”},
{number:“2014010104”,name:“牛耳”,sex:“女”,age:“22”},
{number:“2014010105”,name:“兆司”,sex:“男”,age:“18”},
{number:“2014010106”,name:“胡柳”,sex:“女”,age:“19”},
{number:“2014010107”,name:“刘斯”,sex:“男”,age:“20”},
{number:“2014010108”,name:“孙阳”,sex:“女”,age:“22”},
{number:“2014010109”,name:“郑武”,sex:“男”,age:“21”},
{number:“2014010110”,name:“王雪”,sex:“女”,age:“20”},
{number:“2014010111”,name:“胡柳”,sex:“女”,age:“19”},
{number:“2014010112”,name:“刘斯”,sex:“男”,age:“20”},
{number:“2014010113”,name:“孙阳”,sex:“女”,age:“22”},
{number:“2014010114”,name:“郑武”,sex:“男”,age:“21”},
{number:“2014010115”,name:“王雪”,sex:“女”,age:“20”}
]);
]]>
import mx.managers.PopUpManager;
/*添加按钮事件函数*/
protected function addHandler(event:MouseEvent):void
{
var childWindow:ChildWindow = ChildWindow(PopUpManager.createPopUp(this,ChildWindow,true));
var point:Point = new Point(100,100);
childWindow.x = point.x + 400;
childWindow.y = point.y + 50;
}
/*修改按钮事件函数*/
protected function updateHandler(event:MouseEvent):void
{
var updateWindow:UpdateWindow = UpdateWindow(PopUpManager.createPopUp(this,UpdateWindow,true));
var point:Point = new Point(100,100);
updateWindow.x = point.x + 400;
updateWindow.y = point.y + 50;
updateWindow.stuNo = event.currentTarget.selectedItem.content;
}
]]>
(2)新建一个新增窗口组件,ChildWindow.mxml
ChildWindow.mxml:
代码如下:
xmlns:s=“library://ns.adobe.com/flex/spark”
xmlns:mx=“library://ns.adobe.com/flex/mx” width=“400” height=“300”
close=“closeHandler(event)” title=“新增窗口”>
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
/*关闭按钮函数*/
protected function closeHandler(event:CloseEvent):void
{
PopUpManager.removePopUp(this);
}
/*取消按钮函数*/
protected function cancelHandler(event:MouseEvent):void
{
PopUpManager.removePopUp(this);
}
]]>
(3)新建一个修改界面组件,UpdateWindow.mxml
UpdateWindow.mxml:
代码如下:
xmlns:s=“library://ns.adobe.com/flex/spark”
xmlns:mx=“library://ns.adobe.com/flex/mx” width=“400” height=“300”
close=“closeHandler(event)” title=“修改窗口”>
import mx.events.CloseEvent;
import mx.managers.PopUpManager;
/*关闭按钮函数*/
protected function closeHandler(event:CloseEvent):void
{
PopUpManager.removePopUp(this);
}
/*取消按钮函数*/
protected function cancelHandler(event:MouseEvent):void
{
PopUpManager.removePopUp(this);
}
]]>
3、设计结果
(1)初始化时
这篇文章主要介绍了在MySQL中实现二分查找的详细教程,来自计算机研究生考试原题,需要的朋友可以参考下
给定一个升序排列的自然数数组,数组中包含重复数字,例如:[1,2,2,3,4,4,4,5,6,7,7],问题:给定任意自然数,对数组进行二分查找,返回数组正确的位置,给出函数实现。注:连续相同的数字,返回第一个匹配位置还是最后一个匹配位置,由函数传入参数决定。
我为什么会出这道题目?
二分查找在数据库内核实现中非常重要
在数据库的内核实现中,二分查找是一个非常重要的逻辑,几乎99%以上的SQL语句(所有索引上的范围扫描/等值查询/Unique查询等),都会使用到二分查找进行数据的定位。
考虑一个数据库表t1(a int primary key, b int),表上的b字段有一个B+树索引,表中记录的b字段取值,就是题目中的[1,2,2,3,4,4,4,5,6,7,7]序列。此时,给定以下的两条查询语句,就是使用到了不同的二分查找逻辑:
SQL1:
select * from t1 where b > 4;
SQL2:
select * from t1 where b >= 4;
针对SQL1,索引的二分查找,就需要跳过所有的4,从最后一个4之后开始返回所有记录;针对SQL2,二分查找就需要定位到第一个4,然后顺序读取所有记录。
除此之外,针对数据库中其他的查询逻辑,二分查找还需要附带更多的功能,例如:
SQL3:
select * from t1 where b < 2;
SQL4:
select * from t1 where b <= 2;
由于数据库索引同时支持反向扫描,因此SQL3、SQL4的语句,都可以使用索引反向扫描。反向扫描时,SQL3需要定位到索引中的第一个2;而SQL4,则需要定位到索引的最后一个2,然后开始反向返回满足查询条件的索引记录。
二分查找在程序设计中,是一个十分基础并且易错的功能
第一个真正正确的二分查找算法,在第一个二分查找实现之后的,才被发表出来。通过Google,输入Binary Search或者是二分查找关键字,有大量的相关的文章或者博客讨论此话题。
二分查找实现,需要注意的问题
本文不准备详细介绍一个正确的二分查找应该是如何实现的,毕竟现在网上有着大量的正确版本。接下来,根据批改试卷过程中发现的一些问题,做一些简单的分析,希望对大家实现一个有效的二分查找算法,甚至是一个数据库内可用的二分查找算法,有所帮助。
问题一:是否检查参数的有效性
大量的试卷,在给出此问题的解决算法时,直接拿着low,high参数开始进行计算,但是却没有检查low/high参数。low/high是否相同,数组中是否存在记录?low/high构成的区间是否有效?代码的鲁棒性不足。
在数据库的二分查找实现中,一般是对一个索引页面进行二分查找。索引页面中有可能根本不存在用户的记录(索引页面中的记录全部被删除,又没有与兄弟页面合并时),此时,low/high均为0,此时如果根据low/high计算出来的mid进行记录的读取,就存在逻辑错误。
问题二:二分查找中值的计算
这是一个经典的话题,如何计算二分查找中的中值?试卷中,大家一般给出了两种计算方法:
算法一: mid = (low + high) / 2
算法二: mid = low + (high C low)/2
乍看起来,算法一简洁,算法二提取之后,跟算法一没有什么区别。但是实际上,区别是存在的。算法一的做法,在极端情况下,(low + high)存在着溢出的风险,进而得到错误的mid结果,导致程序错误。而算法二能够保证计算出来的mid,一定大于low,小于high,不存在溢出的问题。
回到数据库二分查找,数据库的一个索引页面(大小一般是8k或者是16k),能够存储的索引记录是有限的,因此肯定不会出现(low + high)溢出的风险。这也是为什么InnoDB中的中值,采用的就是算法一的实现。但是,作为一个严谨的程序设计人员,还是推荐使用算法二,将任何潜在的风险,扼杀于摇篮之中。
问题三:递归实现二分查找
超过一半的试卷,使用了递归调用的方式实现二分查找。不能说递归实现有错,而是在于实现效率问题。总所周知,递归调用存在着压栈/出栈的开销,其效率是比较低下的。而以数据库这样一个极端优化代码效率,提供快速查询响应的系统来说,效率是第一位的。不建议使用递归方式实现二分查找,至少在数据库内核实现中是不允许使用的。据我所知,所有的开源数据库系统,例如:InnoDB,PostgreSQL都未采用递归方式实现二分查找。
问题四:如何查找第一个/最后一个等值
回到题目,要求根据传入的参数不同,返回第一个/最后一个等值项。在本文的背景部分,我也解释了此问题对应的数据库查询(>,>=查询需求是不同的)。在试卷中,超过80%的同学的答案都是先进行二分查找,待定位到相同值之后,再根据传入的flag(用户需求:flag = 1,返回第一个等值项;flag = 0,返回最后一个等值项),进行顺序遍历,直至定位到满足条件的项。
同样,不能说这个实现是错的,但是也存在着性能问题。性能性能性能,永远是数据库内核实现考虑的重点之一(相信也是所有应用程序的一个指标)。数据库中,除了主键索引/Unique索引能够保证键值唯一之外,很多二级辅助索引都是存在相同键值的,有时相同键值的项会超过千项(考虑一个用户的订单,或者是购买记录)。
假设一个索引页面,保存着400项记录,均为相同键值。此时,使用先二分查找,后顺序遍历的算法,二分查找只能使用一次,顺序遍历199次,最终对比了200次。效率非常之低。当然,我也欣喜的看到另外一小部分同学的做法(我期待看到的算法),用flag来纠正每次比较的最终结果,
例如:比较相等(相等用0表示,大于为1,小于为-1),但是flag = 1,则返回纠正后的比较结果为1,需要移动二分查找的high到mid,继续二分(反之,若flag = 0,则返回纠正后的结果为-1,需要移动二分查找的low到mid,继续二分)。如此一来,等值仍旧可以进行二分查找,最终的对比只需要9次,远远小于200次。
此问题,进一步引出了下一个问题,数据库中如何实现一个通用的,更为复杂的二分查找算法?
问题五:数据库中的二分查找实现举例
数据库中的二分查找,更为复杂,需要实现一个通用型的二分查找算法,使用于各种不同的SQL查询场景。
InnoDB针对不同的SQL语句,总结出四种不同的Search Mode,分别为:
#define PAGE_CUR_G 1 >查询
#define PAGE_CUR_GE 2 >=,=查询
#define PAGE_CUR_L 3 <查询>查询>
#define PAGE_CUR_LE 4 <=查询
然后根据这四种不同的Search Mode,在二分查找碰到相同键值时进行调整。例如:若Search Mode为PAGE_CUR_G或者是PAGE_CUR_LE,则移动low至mid,继续进行二分查找;若Search Mode为PAGE_CUR_GE或者是PAGE_CUR_L,则移动high至mid,继续进行二分查找。
我们的TNT引擎,采用了与InnoDB不同的方案,但是也实现了相同的功能。TNT引擎针对相同键值的调整总结为下图,在此我就不做解释了,大家可以尝试着自己进行分析。
/* 操作符 includeKey forward compare result: 1 0 -1 */
=============================================================================
>= 1 1 | 1 -1 -1
= 1 1 | 1 -1 -1
> 0 1 | 1 1 -1
< 0 0 | 1 -1 -1
<= 1 0 | 1 1 -1
=============================================================================
VB中如何实现文本查找功能
实现查找功能的关键在于使用InStr函数,这个函数可以找到指定的字符串在另一字符串中最先出现的位置,我们先来看一看使用这个函数的语法:
InStr([start, ]string1, string2[, compare])
这个函数需要的的参数是起始位置、主体字符串、要查找的字符串;Compare是可选参数。指定字符串比较。此compare参数是可以省略的,也可以是 0, 1或 2。指定0(缺省)做二进制比较。指定1做不区分大小写的文本比较。例如我们要查找在字符串“abcdefg”中是否存在“cd”并返回其位置,则使用下面的语句就可以实现:
pos=InStr(1,“abcdefg”,“cd”)
则pos会返回3表示查找到并且位置为第三个字符开始。这就是“查找”的实现,而“查找下一个”功能的实现就是把当前位置作为起始位置继续查找。
下面举例说明:
放置一个文本框TEXT1供用户输入文本或调入文本文件,用来做在其中查找文本的验证,放置另一个文本框TEXT2供用户输入要查找的字符串,放置两个命令按钮,Command1、Command2,其标题分别为“查找”、“查找下一个”。
在窗体的总体声明部分写如下代码 :
Option Explicit '定义目标位置变量
Private TargetPosition As Integer
'编写一个查找函数
Private Sub FindText(ByVal start_at As Integer)
Dim pos As Integer
Dim target As String
'获取用户输入的要查找的字符串
target = text2.Text
pos = InStr(start_at, text1.Text, target)
If pos > 0 Then
'找到了匹配字符串
TargetPosition = pos
text1.SelStart = TargetPosition - 1
'选中找到的字符串
text1.SelLength = Len(target)
text1.SetFocus
Else '没有找到匹配的字符串
MsgBox “没找到!”
text1.SetFocus
End If
End Sub
'双击“查找”命令按钮:
Private Sub command1_Click '从第一个字符处开始查找
FindText 1
End Sub
'双击“查找下一个”按钮:
Private Sub command2_Click() '从当前位置继续查找
FindText TargetPosition + 1
End Sub
运行程序,在文本框1中输入一些字符串,在文本框2中输入要查找的字符串,单击 “查找”按钮和“查找下一个”按钮进行验证,
在linux中查找文件,替换都是使用命令模式来执行,下面我来介绍在linux中find grep perl配合实现查找替换内容,有需要的朋友可参考,
可以用find配合sed或者perl来完成
查找当前目录下,把
代码如下复制代码替换成
代码如下复制代码find ./ -type f -exec sed -i “s//
content=”text/html; charset=utf-8“ />/g” {} ;
上边是在linux,好像centos也可以,但是FreeBSD上不行,懒得查语法了,
搞了个find+perl的版本
把abc换成def
代码如下复制代码find ./ -type f | xargs perl -pi -e “s/abc/def/g”FreeBSD不行,可能是shell不对。切换到bash,没报错了
上面只是简单的介绍,如果更复杂的大家可自行百度搜索。
,
分享给大家供大家参考。具体实现方法如下:
seq1 = “spam” seq2 = “scam” res = []for x in seq1: if x in seq2: res.append(x)print res
输出结果如下:
[‘s‘, ‘a‘, ‘m‘]
希望本文所述对大家的Python程序设计有所帮助。