瞎扯淡 pythoner 砸场子来了

gaicitadie · March 19, 2012 · Last by ShiningRay replied at June 11, 2012 · 12646 hits

统计一个字符串在另一个字符串中出现的次数,python 只需要一个 count 方法:

>>> '11ab1111ab111ac11111'.count('ab')
2


irb> '11ab1111ab111ac11111'.scan("ab").count
2


1.9.2p290 :001 >  '11ab1111ab111ac11111'.count('ab')
 => 5 

楼主想表达什么?

哎呀。。。怎么 python 和 ruby 的 count 还不一样,哈哈

Ruby 的 "".count 统计的是后面所有的字符

貌似_who 还写过一个 python 与 ruby 转换的程序?

奥运奖牌榜: 国家 金牌数 银牌数 铜牌数 china 37 26 11 usa 30 22 50 russia 30 33 20

中国习惯上先按金牌数排名,金牌数一样的按银牌数再排,如果银牌数再一样就按铜牌数排:

>>> sorted([('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)], key=lambda x:(-x[1],-x[2],-x[3]))
[('china', 37, 26, 11), ('russia', 30, 33, 20), ('usa', 30, 22, 50)]

美国习惯上金牌银牌铜牌都是奖牌,所以按奖牌总数排序:

>>> sorted([('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)], key=lambda x:-(x[1]+x[2]+x[3]))
[('usa', 30, 22, 50), ('russia', 30, 33, 20), ('china', 37, 26, 11)]

python 的排序达到了类似 SQL 查询的能力,只需要告诉它排序的条件就可以了,python 为数据而生

上面的例子是 python 模拟 SQL 的 order by 功能,下面的例子用 python 模拟 SQL 的 where 条件查询

统计金牌数超过 35 的国家:

>>> [x for x in [('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)] if x[1]>35]
[('china', 37, 26, 11)]

统计奖牌总数超过 100 的国家:

>>> [x for x in [('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)] if x[1]+x[2]+x[3]>100]
[('usa', 30, 22, 50)]

@gaicitadie ruby 是

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].select{|x| x[1] > 35}
[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].select{|x| x[1] + x[2] + x[3] > 100}

#6 楼 @gaicitadie order by 的 ruby 代码

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].sort_by{|m| [-m[1], -m[2], -m[3]]}
[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].sort_by{|m| -(m[1] + m[2] + m[3])]}

从楼主的例子直接翻译到 Ruby 1 中国习惯上先按金牌数排名,金牌数一样的按银牌数再排,如果银牌数再一样就按铜牌数排:

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].sort_by{|x| [-x[1],-x[2],-x[3]]}

2 美国习惯上金牌银牌铜牌都是奖牌,所以按奖牌总数排序:

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].sort_by{|x| -(x[1]+x[2]+x[3])}

3 统计金牌数超过 35 的国家:

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].select{|x| x[1] >35}

4 统计奖牌总数超过 100 的国家:

[['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].select{|x| x[1]+x[2]+x[3] > 100}

这两个语言都挺类似,我觉得 ruby 的 select 更直观。

另 楼主这个帖子想表达什么?没看出什么来。如果说只通过 sorted 就说明 python 是为数据而生的话,那 ruby 不也是吗。哈哈

我来写个 Ruby 版本的。

第一个,奖牌排序:

data = [[:china, 27, 26, 11], [:usa, 20, 22, 50], [:russia, 30, 33, 20]]

data.sort_by { |x| [-x[1], -x[2], -x[3]] } # 中国排序方法,按金/银/铜牌数
data.sort_by { |x| -(x[1] + x[2] + x[3]) } # 美国排序方法,按奖牌总数



第二个,奖牌统计:

data.select { |x| x[1] > 35 } # 金牌数超过35的国家
data.select { |x| x[1] + x[2] + x[3] > 100 } # 奖牌总数超过100的国家



哪个更简洁,一目了然了吧。

原来大家都在回复。。等我写出来才发现。

#10 楼 @skandhas 看了你的方法,才想到,select 是更直接的做法。collect 方法会包含 nil 值。

总统选举投票,初步唱票记录:

['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']

根据唱票记录统计每人的票数并按从多到少排序

>>> l = ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']
>>> sorted(set([(i, l.count(i)) for i in l]), key=lambda x:-x[1])
[('Jim', 4), ('bush', 2), ('obama', 1)]

#15 楼 @gaicitadie 不如直接用 collections.Counter

#16 楼 @clearJiang 低版本没有 collections

总统选举投票

l = ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']
l.uniq.collect { |x| [x, l.count(x)] }
=> [["Jim", 4], ["bush", 2], ["obama", 1]] 

#15 楼 @gaicitadie 根据唱票记录统计每人的票数并按从多到少排序:

l = ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']
l.group_by{|i| i}.map{|k,v| [k,v.length] } 

python 要和 ruby 比 文件、字符操作或者数组、Hash 操作的便利性绝对完败,要砸场还不如在性能上一棍子打死 ruby。

这样的帖子应该多一点。长知识。@skandhas cool.

#15 楼 @gaicitadie

['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama'].inject(Hash.new(0)) {|h, e| h[e] += 1; h}.sort_by{|e| -e[1]}


说实话,Python 的 lambda 匿名函数,跟 Ruby 的 Block 相比,从书写上就败了。

随机设置验证码的 4 个字符 (不包括图片处理部分)

>>> import random
>>> s = 'ABCDEFGHIJKLMNPRSTUVWXYZ'
>>> ''.join(random.sample((s),4))
'EXSG'
>>> ''.join(random.sample((s),4))
'TGYN'
>>> ''.join(random.sample((s),4))
'MEYP'
>>> ''.join(random.sample((s),4))
'TGIF'
>>> ''.join(random.sample((s),4))
'JDWF'

#24 楼 @gaicitadie

('A'..'Z').to_a.sample(4).join

#15 楼 @gaicitadie 你这个算法是 O(n ^ 2) 的,应该用 reduce

def stat(acc, x):
  acc.setdefault(x, 0)
  acc[x] += 1
  return acc
sorted(reduce(stat, 
  ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama'], {}).iteritems(),
    key = lambda x: -x[1])

@skandhas cool,加上个排序。

#26 楼 @reus reduce 不如列表解析快,虽然 list.count 会重复统计

#27 楼 @huyong36 对,是忘了排序

l = ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']
l.group_by{|i| i}.map{|k,v| [k,v.length] }.sort_by{|name,count| -count } 

风格不同而已,用起来都是一样方便。这个就是让我喜欢 Python 和 Ruby 的原因之一。

#28 楼 @gaicitadie 就是慢在 count 调用上,for i in l 遍历数组,且每个元素又再 count 遍历一次,O(n ^ 2) reduce 只需要遍历一次,O(n) 不信可以测试下

这帖应该是捧场帖,我喜欢这样的学习。

  • 字符串查找
# python
>>> '11ab1111ab111ac11111'.count('ab')
2
# Ruby 
ruby-1.9.2-p290 >   '11ab111123ab111ac11111'.count 'ab', 'b'
2

  • 奖牌排序
# python
>>> sorted([('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)], key=lambda x:(-x[1],-x[2],-x[3]))
[('china', 37, 26, 11), ('russia', 30, 33, 20), ('usa', 30, 22, 50)]
# ruby
ruby-1.9.2-p290 > [['china',37,26,11], ['usa',30,22,50],['russia',30,33,20]].sort_by {|name,j,y,t| [-j,-y,-t] }
 => [["china", 37, 26, 11], ["russia", 30, 33, 20], ["usa", 30, 22, 50]] 

  • 奖牌统计
# python
>>> sorted([('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)], key=lambda x:-(x[1]+x[2]+x[3]))
[('usa', 30, 22, 50), ('russia', 30, 33, 20), ('china', 37, 26, 11)]
# ruby
ruby-1.9.2-p290 > [['china',37,26,11], ['usa',30,22,50],['russia',30,33,20]].sort_by {|name,j,y,t| [-j + -y + -t] }
 => [["usa", 30, 22, 50], ["russia", 30, 33, 20], ["china", 37, 26, 11]] 

捧场.. js:

'11ab1111ab111ac11111'.match(/ab/g).length;

'11ab1111ab111ac11111'.split('ab').length - 1;

中式排名:

[[37, 26, 11], [30, 22, 50], [30, 33, 20]].sort().reverse();

总统选举投票,初步唱票记录:

# ruby
>>> l = ['Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama']
>>> sorted(set([(i, l.count(i)) for i in l]), key=lambda x:-x[1])
[('Jim', 4), ('bush', 2), ('obama', 1)]
# ruby
ruby-1.9.2-p290 >  ['bush','Jim', 'bush', 'Jim', 'Jim', 'Jim', 'bush', 'obama'].each_with_object({}) {|name,s| s[name] = s.fetch(name,0) + 1 }.sort
 => [["Jim", 4], ["bush", 3], ["obama", 1]]  

#34 楼 @hysios

'11ab111123ab111ac11111'.count 'ab', 'b'

这样不对吧...这样只是找出来字符串里出现 b 的次数。

irb(main):106:0> '11ab111123ab111ac11111b'.count 'ab', 'b'
=> 3

@huyong36 thx count 是没办法实现的,别的方法也不错

#40 楼 @hysios 恩,请教

irb(main):115:0> '11ab111123ab111c11111'.count  'a'
=> 2
irb(main):114:0> '11ab111123ab111c11111'.count  'ab'
=> 4

字符可以统计,为什么字符串不能。。

@huyong36 count([other_str]+) → fixnum click to toggle source Each other_str parameter defines a set of characters to count. The intersection of these sets defines the characters to count in str. Any other_str that starts with a caret (^) is negated. The sequence c1–c2 means all characters between c1 and c2.

Unknow user #43 March 19, 2012
gaicitadie = [['china',37,26,11], ['usa',30,22,50], ['russia',30,33,20]].tap do |man|
  def man.make_self(&process); process.call self; end
  def man.become_egghead
    `python -c "print( sorted([('china',37,26,11), ('usa',30,22,50), ('russia',30,33,20)], key=lambda x:(-x[1],-x[2],-x[3])) )"`
  end
  def man.glow_up
    dont_be_shy = true
    unless self.respond_to? :more_elegant, dont_be_shy
      def self.more_elegant
        self.sort_by { |country, glods, silvers, bronzes| [-glods,-silvers,-bronzes] }
      end
    end
    if self.respond_to? :become_egghead
      class << self; remove_method :become_egghead; end 
    end
    self
  end
end
gaicitadie.make_self &:become_egghead
gaicitadie.glow_up.make_self &:more_elegant



#41 楼 @huyong36 ruby 的 count 统计的是字符的数量 所以'11ab111123ab111c11111'.count 'ab'等同于'11ab111123ab111c11111'.count 'a' + '11ab111123ab111c11111'.count 'b'

简而言之就是 取每一个字符的 count 的交集

#41 楼 @huyong36 count 是统计所有的字符,并不会把参数当成字符串处理

合并两个字典/哈希,重复的项目,两个值相加

hash1.merge(hash2) {|dupkey,val1,val2| val1 + val2 }

楼主来个 Python 的写法?

method_missing, 楼主来个??

#48 楼 @FenRagwort ,这个暂时只想到了普通方法

for k,v in hash2.items():
    if k in hash1:
        hash1[k] += v
    else:
        hash1.setdefault(k,v)

#19 楼 @skandhas

的确酷,不说说实在的。group_by 用来做这个,真是有点大才小用了。

#49 楼 @hhuai

class Foo:
  def __getattr__(self, name):
    def _foo(*arg, **kwargs):
      return self.method_missing(name, *arg, **kwargs)
    return _foo

  def method_missing(self, name, *args, **kwargs):
    print name, args, kwargs

a = Foo()
a.foo('bar', baz = 'baz')


#34 楼 @hysios

你这个算法不对, 'ab', 和 'b'先求交集 ,然后统计 b 的个数。

ruby-1.9.2-p290 >   '11ab111123ab111ac11111b'.count 'ab', 'b'

结果将是 3

昏..... 看样子应该看完再回复。

a=[]
h={}
"{'a':'va','b':'vb','c':'vc'}".gsub(/([\w+\d+]+)/) {|s| a+=s.to_a}
a.each{|x| h.store(x,a[a.index(x)+1]) if a.index(x)%2==0}
h
=> {"c"=>"vc", "b"=>"vb", "a"=>"va"}

各位 这个还能简化么 想了半天 才写成这样

#55 楼 @jhjguxin 是想转换成 hash 吗?把:替换成=>,然后 eval 不行吗?

eval "{'a':'va','b':'vb','c':'vc'}".gsub(':','=>')

#55 楼 @jhjguxin #56 楼 @skandhas

你们这是在胡闹么 =。=

require 'json'
wtf = "{'a':'va','b':'vb','c':'vc'}".gsub("'",'"')
JSON.parse wtf
# => {"a"=>"va", "b"=>"vb", "c"=>"vc"}

#58 楼 @fredwu 用 json 库,恩,学习了。thx!

@fredwu 不是胡闹 是新手 还想不出来 有这些方法 学习了哈 ps 觉得可以把这个楼 盖起来 楼下的说好不好

学习学习

我想起了做 SPOJ 的日子

You need to Sign in before reply, if you don't have an account, please Sign up first.