下面给出了一个用 Python 和 C++ 编写的程序,它执行以下任务:从 stdin 读取空格分隔的单词,将按字符串长度排序的唯一单词连同每个唯一单词的计数打印到 stdout。一行输出的格式为:长度、计数、单词。
例如,使用这个输入文件(同义词库的 488kB) http://pastebin.com/raw.php?i=NeUBQ22T
带格式的输出是这样的:
1 57 "
1 1 n
1 1 )
1 3 *
1 18 ,
1 7 -
1 1 R
1 13 .
1 2 1
1 1 S
1 5 2
1 1 3
1 2 4
1 2 &
1 91 %
1 1 5
1 1 6
1 1 7
1 1 8
1 2 9
1 16 ;
1 2 =
1 5 A
1 1 C
1 5 e
1 3 E
1 1 G
1 11 I
1 1 L
1 4 N
1 681 a
1 2 y
1 1 P
2 1 67
2 1 y;
2 1 P-
2 85 no
2 9 ne
2 779 of
2 1 n;
...
这是C++的程序
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
bool compare_strlen (const std::string &lhs, const std::string &rhs) {
return (lhs.length() < rhs.length());
}
int main (int argc, char *argv[]) {
std::string str;
std::vector<std::string> words;
/* Extract words from the input file, splitting on whitespace */
while (std::cin >> str) {
words.push_back(str);
}
/* Extract unique words and count the number of occurances of each word */
std::set<std::string> unique_words;
std::map<std::string,int> word_count;
for (std::vector<std::string>::iterator it = words.begin();
it != words.end(); ++it) {
unique_words.insert(*it);
word_count[*it]++;
}
words.clear();
std::copy(unique_words.begin(), unique_words.end(),
std::back_inserter(words));
// Sort by word length
std::sort(words.begin(), words.end(), compare_strlen);
// Print words with length and number of occurances
for (std::vector<std::string>::iterator it = words.begin();
it != words.end(); ++it) {
std::cout << it->length() << " " << word_count[*it] << " " <<
*it << std::endl;
}
return 0;
}
这是 Python 程序:
import fileinput
from collections import defaultdict
words = set()
count = {}
for line in fileinput.input():
line_words = line.split()
for word in line_words:
if word not in words:
words.add(word)
count[word] = 1
else:
count[word] += 1
words = list(words)
words.sort(key=len)
for word in words:
print len(word), count[word], word
对于 C++ 程序,使用的编译器是带有 -O3 标志的 g++ 4.9.0。
使用的Python版本是2.7.3
C++ 程序花费的时间:
time ./main > measure-and-count.txt < ~/Documents/thesaurus/thesaurus.txt
real 0m0.687s
user 0m0.559s
sys 0m0.123s
Python 程序花费的时间:
time python main.py > measure-and-count.txt < ~/Documents/thesaurus/thesaurus.txt
real 0m0.369s
user 0m0.308s
sys 0m0.029s
Python 程序比 C++ 程序快得多,并且在输入较大时相对更快。这里发生了什么?我对 C++ STL 的使用不正确吗?
编辑:
根据评论和答案的建议,我将 C++ 程序更改为使用 std::unordered_set 和 std::unordered_map。
更改了以下几行
#include <unordered_set>
#include <unordered_map>
...
std::unordered_set<std::string> unique_words;
std::unordered_map<std::string,int> word_count;
编译命令:
g++-4.9 -std=c++11 -O3 -o main main.cpp
这仅略微提高了性能:
time ./main > measure-and-count.txt < ~/Documents/thesaurus/thesaurus.txt
real 0m0.604s
user 0m0.479s
sys 0m0.122s
Edit2:一个更快的 C++ 程序
这是 NetVipeC 的解决方案、Dieter Lücking 的解决方案和 this question 的最佳答案的组合。 .真正的性能 killer 是默认使用无缓冲读取 的cin。用 std::cin.sync_with_stdio(false); 解决。该解决方案还使用单个容器,利用 C++ 中有序的 map。
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
struct comparer_strlen {
bool operator()(const std::string& lhs, const std::string& rhs) const {
if (lhs.length() == rhs.length())
return lhs < rhs;
return lhs.length() < rhs.length();
}
};
int main(int argc, char* argv[]) {
std::cin.sync_with_stdio(false);
std::string str;
typedef std::map<std::string, int, comparer_strlen> word_count_t;
/* Extract words from the input file, splitting on whitespace */
/* Extract unique words and count the number of occurances of each word */
word_count_t word_count;
while (std::cin >> str) {
word_count[str]++;
}
// Print words with length and number of occurances
for (word_count_t::iterator it = word_count.begin();
it != word_count.end(); ++it) {
std::cout << it->first.length() << " " << it->second << " "
<< it->first << '\n';
}
return 0;
}
运行时
time ./main3 > measure-and-count.txt < ~/Documents/thesaurus/thesaurus.txt
real 0m0.106s
user 0m0.091s
sys 0m0.012s
Edit3: Daniel 提供了一个漂亮简洁的 Python 程序版本,它的运行时间与上面的版本大致相同:
import fileinput
from collections import Counter
count = Counter(w for line in fileinput.input() for w in line.split())
for word in sorted(count, key=len):
print len(word), count[word], word
运行时:
time python main2.py > measure-and-count.txt.py < ~/Documents/thesaurus/thesaurus.txt
real 0m0.342s
user 0m0.312s
sys 0m0.027s
最佳答案
用这个测试,它一定比原来的C++快。
变化是:
words保存单词(word_count 中已经保存了单词)。unique_words (在 word_count 中只有独特的单词)。消除了单词的排序(在 map 中更新了顺序,现在 map 中的单词按长度排序,相同长度的单词按字典顺序排列。
#include <vector>
#include <string>
#include <iostream>
#include <set>
#include <map>
struct comparer_strlen_functor {
operator()(const std::string& lhs, const std::string& rhs) const {
if (lhs.length() == rhs.length())
return lhs < rhs;
return lhs.length() < rhs.length();
}
};
int main(int argc, char* argv[]) {
std::cin.sync_with_stdio(false);
std::string str;
typedef std::map<std::string, int, comparer_strlen_functor> word_count_t;
/* Extract words from the input file, splitting on whitespace */
/* Extract unique words and count the number of occurances of each word */
word_count_t word_count;
while (std::cin >> str) {
word_count[str]++;
}
// Print words with length and number of occurances
for (word_count_t::iterator it = word_count.begin(); it != word_count.end();
++it) {
std::cout << it->first.length() << " " << it->second << " " << it->first
<< "\n";
}
return 0;
}
新版本的阅读循环,逐行阅读和拆分。需要#include <boost/algorithm/string/split.hpp>
while (std::getline(std::cin, str)) {
for (string_split_iterator It = boost::make_split_iterator(
str, boost::first_finder(" ", boost::is_iequal()));
It != string_split_iterator(); ++It) {
if (It->end() - It->begin() != 0)
word_count[boost::copy_range<std::string>(*It)]++;
}
}
在 Core i5、8GB 内存、GCC 4.9.0、32 位中进行测试,运行时间为 238 毫秒。用 std::cin.sync_with_stdio(false); 更新了代码和 \n按照提议。
关于python - 在这种情况下,为什么 Python 比 C++ 快?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24895881/
类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc
关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
这是在Ruby中设置默认值的常用方法:classQuietByDefaultdefinitialize(opts={})@verbose=opts[:verbose]endend这是一个容易落入的陷阱:classVerboseNoMatterWhatdefinitialize(opts={})@verbose=opts[:verbose]||trueendend正确的做法是:classVerboseByDefaultdefinitialize(opts={})@verbose=opts.include?(:verbose)?opts[:verbose]:trueendend编写Verb
它不等于主线程的binding,这个toplevel作用域是什么?此作用域与主线程中的binding有何不同?>ruby-e'putsTOPLEVEL_BINDING===binding'false 最佳答案 事实是,TOPLEVEL_BINDING始终引用Binding的预定义全局实例,而Kernel#binding创建的新实例>Binding每次封装当前执行上下文。在顶层,它们都包含相同的绑定(bind),但它们不是同一个对象,您无法使用==或===测试它们的绑定(bind)相等性。putsTOPLEVEL_BINDINGput
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re