Maison > Questions et réponses > le corps du texte
就是 现在有一个log 里面全都是访问者的ip(数据很大很大) 一行一个ip
比如
123.22.22.187
123.22.22.182
123.22.21.187
123.22.42.187
123.23.22.187
123.22.22.182
121.22.22.182
....
怎么查出来访问次数最多的10个IP?
方式:
第一步:
如下读取:
声明一个变量 dictionary <string ,long> record
123.22.22.187
123.22.22.182
123.22.21.187
123.22.42.187
123.23.22.187
123.22.22.182
121.22.22.182
先与蓝色部分为key ,key 出现的次数为value 存在 record中。
这样 ,record的最大个数是255个,不算多,更说不上要多少内存。
再来一次大扫除,
使record 剩下 最多的 10 个元素
以这10 个元素为条件,再扫描一次表,把符合条件的数据写到另一个[文件A]中,
第二步:
扫描 [文件A] 以下面数据蓝色部分为key ,以出现次数为value 写到 变量 dictionary <string ,long> record 中
123.22.22.187
123.22.22.182
123.22.21.187
123.22.42.187
123.23.22.187
123.22.22.182
121.22.22.182
。。。
第三步:
。。。
第四步:
。。。
就这样,
用4 步相同的方法,提出最多的数据:10条,
问题,上面这种方式感觉不行啊,是我没理解吗??
比如说:
123,125,196,158,假设这个ip地址出现的次数最多,那么如下,
121,123
121,14
121,56
123,125,196,158,
123,125,196,158,
如果分段比较次数,那么123,125,196,158, 这个ip在第一步就被淘汰了?
大家讲道理2017-04-18 10:33:54
a.b.c.d
Traiter une première.
Tous les fichiers sont divisés en plusieurs lectures (par exemple 255 fois).
Les enregistrements sont ensuite stockés dans 255 fichiers, correspondant à un (tel que 1.b.c.d ; 2.b.c.d ;)
De cette façon, vous pouvez obtenir les dix plus grands.
Ensuite, traitez avec b.
. . .
J'ai enfin la réponse.
巴扎黑2017-04-18 10:33:54
Idée de base
对所有的ip进行分组,统计出现次数,ip做key,出现次数做val,保存在关联数组中
数组按照键值(出现次数)降序排序,取出前 10 条记录
Bien que ce ne soit pas java语言描述的
, javascript描述
devrait être compréhensible Quoi qu'il en soit, je l'ai testé et il peut produire votre effet :
Ce qui suit est l'exemple de code complet :
var data = [123.22.22.187 , 123.22.22.187 ....]; // 等价于日志中每行ip
var data = getCount(data); // 对所有的ip进行分组,统计出现次数
// ip做key,出现次数做val,保存在关联数组中
var rel = getRecord(data , 10 , 'desc'); // 这个就是你想的结果了
/*
* ip 分组并统计次数的具体实现
* @param Array data 日志文件中存放的那些所有ip组成的数组
* @return Object
*/
function getCount(data){
var rel= {}; // 根据ip进行分组后的结果,由于js没有关联数组
// 所以用对象替换
var i;
var count;
var n;
var cur;
var curC;
// 判断是否已经统计过了的
var checkIsCount = function(ip){
var k;
for (k in rel)
{
if (k === ip) {
return true;
}
}
return false;
};
// 每次固定一个 ip
// 先判断当前 ip 在 rel 中是否已经存在(排除已被统计的ip,避免重复统计)
// 不存在的时候,开始统计其出现次数
for (i = 0; i < data.length; ++i)
{
cur = data[i];
count = 1;
if (!checkIsCount(cur)) {
for (n = i + 1; n < data.length; ++n)
{
curC = data[n];
if (cur === curC) {
count++;
}
}
rel[cur] = count;
}
}
// 保存了所有不同ip,及其出现次数的对象
console.log('ip进行了分组并统计后的结果:' , rel);
return rel;
}
/*
* 数组按照键值(出现次数)降序排序,取出前 len 条记录
* @param Object data 分组并统计出现次数后的对象
* @param Number len 取出多少条
* @param String sortType 升序还是降序(asc | desc)
* @return Array
*/
function getRecord(data , len , sortType){
var rel = {};
var result = [];
var k;
var k1;
var curKey;
var count = 0;
// 检查 ip 是否已被获取
var checkSorted = function(ip){
var k;
for (k in rel)
{
if (k === ip) {
return true;
}
}
return false;
};
// 排序算法:选择排序
for (k in data)
{
if (count >= len) {
break;
}
curKey = k;
if (!checkSorted(k)) {
for (k1 in data)
{
if (!checkSorted(k1)) {
if (sortType === 'asc' ? data[curKey] > data[k1] : data[curKey] < data[k1]) {
curKey = k1;
}
}
}
// 按照键值排序后的最大值|最小值
rel[curKey] = data[curKey];
// 返回可视化结果
result.push(curKey);
// 获取的长度增加
count++
}
}
// 按照键值排序后的 len 长度的记录
console.log('取出指定长度记录的实际结果:' , rel);
console.log('取出指定长度记录的可视化结果:' , result);
return result;
}
PHP中文网2017-04-18 10:33:54
Cette question doit être divisée en deux parties pour comprendre,
1 Le fichier est très volumineux et l'efficacité de lecture est faible
2 Trouvez les 10 premiers enregistrements avec le plus d'occurrences
Question 1 : Pour la lecture de fichiers volumineux, vous pouvez utiliser l'implémentation Java AIO pour lire les fichiers de manière asynchrone
Question 2 : LindedList doit être étendue chaque fois qu'un enregistrement est ajouté, vérifiez d'abord s'il existe un enregistrement et, si c'est le cas, avancez la position de l'enregistrement (. cela ressemble plus à l'algorithme de mise en cache Java Memcached)
巴扎黑2017-04-18 10:33:54
Ces types de problèmes ont tous la même idée, « diviser pour mieux régner ».
Chaque IP équivaut à un nombre entier de 32 bits. Parcourez toutes les IP dans le journal, divisez-les en n fichiers selon la plage de valeurs et enregistrez-les (assurez-vous que chaque fichier est suffisamment petit dans ce cas). la même adresse IP sera définitivement divisée dans le même fichier ; puis traitez ces n fichiers un par un, et comptez les 10 premières adresses IP qui apparaissent dans chaque fichier, enfin, obtenez le top 10 de ces 10*n IP ;
ringa_lee2017-04-18 10:33:54
Utilisez des expressions régulières pour déterminer le premier nombre au début de l'IP :
1.2.3\n
4.5.6\n
1.2.3\n
L'IP la plus fréquente est le numéro en début de ligne