给我一把榔头,满世界都是钉子

一篇文章存成一个巨大的文件,总共大约有一亿个单词,要找出里面重复次数最多的。怎么做?

Hadoop是一把威力巨大的榔头,在使用过Hadoop之后,看着任何东西都想把它给map reduce了。有一个关于Jeff Dean的小笑话,说在睡不着觉的时候,一般人是数羊,Jeff Dean是map reduce他的羊群。所以,我的办法是,把这个文件拆分成若干个小文件,在map过程用hash算法保证相同的单词落入一个文件(这点很重要),计算单词出现次数,在reduce过程取得重复次数最多的单词来。

但是,只有一亿个单词,简单估算一下,一个字母占据两个字节,假设单词平均长度5,即便是最极端情况,这些单词里面没有重复,单词本身也就消耗1G而已;而实际上一篇文章单词的重复率是非常高的,这个数据量完全可以放在内存里面计算。还没完,不一定非得要用Hash,如果借由Trie树,可以节点压缩,占用更少的空间。

这只是一个用榔头来敲钉子的一个小例子而已,在我刚学算法的时候,那时候刚接触外排序,这样的问题我或许会第一反应使用外排序来做,在那个时候,这把榔头就是外排序。但实际上呢,外排序的效率比上面提到的方法都低得多,只有在内存实在不够用的时候才适合考虑(即便在内存不够用的情况下,我们依然可以利用hash,把大文件划分成若干个小到内存可以容纳为止的文件,分别计算以后在来归并求最大数,目的就是要尽量避免外排序带来的大量磁盘读写)。

如果再把思路放宽一点,真的需要统计所有的单词吗?其实对于一篇文章来说,其中的内容都是有文字意义的,换言之,只有很少的单词可能成为“重复最多”的,这个数量应该是非常非常有限的。比如在遇到一个“is”的时候,我们知道要把它列入统计范畴,但是遇到“distribution”这样的词呢,大可跳过。

还可以找得到很多这样的榔头,比如概率公式,C(m,n)和A(m,n),即组合数和排列数,对于某些概率、混合、排列的问题就用它来套;再比如常见的榔头——动态规划,学了以后看到求最优解问题就很想用DP来解;还有在数据量很大的情况下利用hash、区域划分等等“分而治之”的化简思想……但是,这些都是常规思路,就如同Top K问题用堆排序来求解,寻找“不出现”的单词就使用bit map,“不重复出现”的单词就使用2-bit map等等这样的问题一样,终归是简单粗暴那一类的。即便解决了问题,也没有给人眼前一亮的“巧妙”的感觉。

跳出算法,在很多工程问题上也有类似的体会。记得以前在做一个项目的单元测试,Easy Mock + Easy Mock Extension + Power Mock,这样一套库,mock的能力实在强大,几乎没有测试不了的代码了,于是就拿了这把榔头到处砸,却忘了单元测试的最终目的是什么,那一些代码是值得做单元测试的。后来利用ant给测试环境中,不关心逻辑的那一层,使用自己写的桩代码mock掉,并且去掉了好多价值不大的测试代码(在代码更新的时候测试代码需要同步维护,这个成本不划算,所以我们把一些价值有但不大的单元测试用例合并或者删除了),层次反而更清楚,测试代码反而更易懂了。

前些日子和我们组的数学达人讨论问题的时候他说,我们最常见的最通用的榔头,主要还是在“解空间的搜索”和“解的构造”这两方面。如果能构造,复杂程度往往就要低于搜索,这是一个递进;而另一方面,任何一个实际问题都是有额外信息的,通用的榔头却是不考虑这些实际信息的,就像这个求重复次数最多的单词问题一样,文件有多大、文件内存放的是一篇实际有意义的文章,等等(再比如如果这个文件里面不是一亿个单词,而是一亿个整数呢),这些都是额外的信息,这是另一个递进。利用这些,简化了问题,就可以杀鸡不用牛刀了吧。

文章系本人原创,转载请保持完整性并注明出自《四火的唠叨》

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
SQLAlchemy 是一个 SQL 工具包和对象关系映射(ORM)库,用于 Python 编程语言。它提供了一个高级的 SQL 工具和对象关系映射工具,允许开发者以 Python 类和对象的形式操作数据库,而无需编写大量的 SQL 语句。SQLAlchemy 建立在 DBAPI 之上,支持多种数据库后端,如 SQLite, MySQL, PostgreSQL 等。 SQLAlchemy 的核心功能: 对象关系映射(ORM): SQLAlchemy 允许开发者使用 Python 类来表示数据库表,使用类的实例表示表中的行。 开发者可以定义类之间的关系(如一对多、多对多),SQLAlchemy 会自动处理这些关系在数据库中的映射。 通过 ORM,开发者可以像操作 Python 对象一样操作数据库,这大大简化了数据库操作的复杂性。 表达式语言: SQLAlchemy 提供了一个丰富的 SQL 表达式语言,允许开发者以 Python 表达式的方式编写复杂的 SQL 查询。 表达式语言提供了对 SQL 语句的灵活控制,同时保持了代码的可读性和可维护性。 数据库引擎和连接池: SQLAlchemy 支持多种数据库后端,并且为每种后端提供了对应的数据库引擎。 它还提供了连接池管理功能,以优化数据库连接的创建、使用和释放。 会话管理: SQLAlchemy 使用会话(Session)来管理对象的持久化状态。 会话提供了一个工作单元(unit of work)和身份映射(identity map)的概念,使得对象的状态管理和查询更加高效。 事件系统: SQLAlchemy 提供了一个事件系统,允许开发者在 ORM 的各个生命周期阶段插入自定义的钩子函数。 这使得开发者可以在对象加载、修改、删除等操作时执行额外的逻辑。
GeoPandas是一个开源的Python库,旨在简化地理空间数据的处理和分析。它结合了Pandas和Shapely的能力,为Python用户提供了一个强大而灵活的工具来处理地理空间数据。以下是关于GeoPandas的详细介绍: 一、GeoPandas的基本概念 1. 定义 GeoPandas是建立在Pandas和Shapely之上的一个Python库,用于处理和分析地理空间数据。 它扩展了Pandas的DataFrame和Series数据结构,允许在其中存储和操作地理空间几何图形。 2. 核心数据结构 GeoDataFrame:GeoPandas的核心数据结构,是Pandas DataFrame的扩展。它包含一个或多个列,其中至少一列是几何列(geometry column),用于存储地理空间几何图形(如点、线、多边形等)。 GeoSeries:GeoPandas中的另一个重要数据结构,类似于Pandas的Series,但用于存储几何图形序列。 二、GeoPandas的功能特性 1. 读取和写入多种地理空间数据格式 GeoPandas支持读取和写入多种常见的地理空间数据格式,包括Shapefile、GeoJSON、PostGIS、KML等。这使得用户可以轻松地从各种数据源中加载地理空间数据,并将处理后的数据保存为所需的格式。 2. 地理空间几何图形的创建、编辑和分析 GeoPandas允许用户创建、编辑和分析地理空间几何图形,包括点、线、多边形等。它提供了丰富的空间操作函数,如缓冲区分析、交集、并集、差集等,使得用户可以方便地进行地理空间数据分析。 3. 数据可视化 GeoPandas内置了数据可视化功能,可以绘制地理空间数据的地图。用户可以使用matplotlib等库来进一步定制地图的样式和布局。 4. 空间连接和空间索引 GeoPandas支持空间连接操作,可以将两个GeoDataFrame按照空间关系(如相交、包含等)进行连接。此外,它还支持空间索引,可以提高地理空间数据查询的效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值