Hash 在线购物网站的日志文件中有一百万条记录。查找不同的IP地址

Hash 在线购物网站的日志文件中有一百万条记录。查找不同的IP地址,hash,Hash,这是一道技术测试题。日志文件中有一百万条记录。这些是在线购物网站的网站点击记录。记录类型为: TimeStamp:Date,time ; IP address; ProductName 查找不同的IP地址和最流行的产品。最有效的方法是什么?一种解决方案是散列。如果解决方案是散列,请说明如何有效地对其进行散列,因为有一百万条记录。在现实世界中,如果这是一次性或偶然的事情,我只需将数据插入数据库并运行一些基本查询 因为这是一个家庭作业,教授可能不想做这个。IP地址实际上只是一个32位的数字。我可以

这是一道技术测试题。日志文件中有一百万条记录。这些是在线购物网站的网站点击记录。记录类型为:

TimeStamp:Date,time ; IP address; ProductName

查找不同的IP地址和最流行的产品。最有效的方法是什么?一种解决方案是散列。如果解决方案是散列,请说明如何有效地对其进行散列,因为有一百万条记录。

在现实世界中,如果这是一次性或偶然的事情,我只需将数据插入数据库并运行一些基本查询

因为这是一个家庭作业,教授可能不想做这个。IP地址实际上只是一个32位的数字。我可以将每个IP转换为它的32位等价物,而不是创建散列


由于这是家庭作业,其余部分“留给读者作为练习。”

我最近做了类似的家庭作业,不确定总行数,但数量相当多。关键是,即使有一百万条记录,你的计算机也可能很快做到这一点

在哈希表上我同意你的观点,我会用稍微不同的方式回答这两个问题。 第一个,我将对照哈希表检查每个ip,如果它存在,什么也不做。如果它不存在,则将其添加到哈希表中,并递增一个计数器。在程序结束时,计数器将告诉您有多少个唯一的IP


第二步,我将散列产品名称并将其放入哈希表中。每次在表中找到匹配项时,我都会增加与hashkey关联的值。最后,循环遍历哈希表的所有键和值,并找到最高值。这是最受欢迎的产品。

一百万条日志记录确实是一个非常小的数字;只需读入它们,并保留一组IP地址和从产品名称到提及次数的dict——您并没有提到任何特定的语言约束,所以我假设一种能够(隐式地)代表您对这些字符串进行出色哈希处理的语言是可以接受的(Perl、Python、Ruby、Java、C#等,都有很好的功能)

例如,在Python中:

import collections
import heapq

ipset = set()
prodcount = collections.defaultdict(int)

numlines = 0
for line in open('logfile.txt', 'r'):
  timestamp, ip, product = line.strip().split(';')
  ipset.add(ip)
  prodcount[product] += 1
  numlines += 1

print "%d distinct IP in %d lines" % (len(ipset), numlines)
print "Top 10 products:"

top10 = heapq.nlargest(10, prodcount, key=prodcount.get)
for product in top10:
  print "%6d %s" % (prodcount[product], product)

首先,一百万行根本不是一个大文件

一个简单的Perl脚本可以在6秒钟内完成270万行的脚本,而不必考虑太多算法

在任何情况下,散列都是一种方法,如图所示,不需要在整数表示上进行散列

如果我们谈论的是一个非常大的文件,那么I/O将成为瓶颈,因此随着文件变大,哈希方法的相关性越来越小

从理论上讲,在像C这样的语言中,对整数进行哈希运算可能比对字符串进行哈希运算要快,但我怀疑,在一种适合此任务的语言中,哈希运算是否真的会产生影响。像如何有效地读取文件这样的事情更重要

代码


我还将该文件读入数据库,并将其链接到另一个日志文件名和导入日期/时间表

这是因为在现实世界中,你需要经常这样做。该公司希望能够随时查看趋势,因此很快就会有人问你这样的问题:“这是不是比上个月的日志文件更独特的IP地址?”以及“最受欢迎的产品每周的变化情况如何”


根据我的经验,在你所描述的面试场景中回答这些问题的最佳方式是展示对现实世界情况的了解。解析日志文件(每天?每周?每月?)并将其读入数据库的工具,在该数据库中,一些查询、图表等可以提取所有数据,尤其是跨多个日志文件,这样写起来会花费更长的时间,但会更加有用和可用。

与其他人编写的一样,只有两个哈希表。一个用于IP,一个用于产品。你可以计算两者的发生率,但你只关心后者的“产品流行度”

散列的关键是有一个有效的散列键,而散列效率意味着这些键是均匀分布的。糟糕的密钥选择意味着会有很多冲突,哈希表的性能将受到影响

由于懒惰,我很想创建一个
字典
,并希望IPAddress类的实现者能够正确地创建散列键

Dictionary<IPAddress, int> ipAddresses = new Dictionary<IPAddress, int>();
Dictionary<string, int> products = new Dictionary<string,int>();

只需按两个感兴趣的字段对文件进行排序。这就避免了对散列函数的担心,而且在一百万个记录集上也可以正常工作

通过这种方式对IP地址进行排序,还可以轻松提取其他感兴趣的信息,例如来自同一子网的访问。

不同的IP地址:

$ cut -f 2 -d \; | sort | uniq
最受欢迎的产品:

$ cut -f 3 -d \; | sort | uniq -c | sort -n
如果您可以这样做,shell可以这样编写脚本。

独特的IP:

$ awk -F\; '{print $2}' log.file | sort -u
伯爵

{ a[$0]++ }

END {
    for(key in a) {
        print a[key] " " key;
    }
}
十大最受欢迎的项目:

$ awk -F\; '{print $3}' log.file | awk -f count.awk | sort -r -n | top

当你说日志文件时,你指的是一个文本文件,每行有一条记录?是的,记录在文本文件(平面)中。是否有新行分隔每个条目?@Aditya:标签不是用来做这个的。请阅读常见问题。也许他只是想要他的回滚徽章:PIt不是一个家庭作业问题。就在昨天,一家公司在技术测试中要求它进行校园实习。由于保密协议,我不能透露公司名称。即使我不应该问这个问题,但我想知道这个问题的最佳解决方案,这样我就能在未来表现出色。这和家庭作业一样。这是用来衡量你的东西。你想用它来衡量你让别人为你做这件事的能力。为什么是-1?他们的问题被标记为家庭作业,所以我给出了一个合理的提示,但没有给出解决方案。那么为什么我们还有日志文件和日志文件分析工具呢?我不是说你错了,但你不需要数据库。原始数据量可能太大,无法存储在数据库中,因此您可能会丢失数据
$ awk -F\; '{print $2}' log.file | sort -u
{ a[$0]++ }

END {
    for(key in a) {
        print a[key] " " key;
    }
}
$ awk -F\; '{print $3}' log.file | awk -f count.awk | sort -r -n | top