❶ (求算法高手!)将一个正整数表示为N个不同的正整数之和。
200分悬赏啊,我要试一试啊。
首先是思路:
n能被拆分成不同的整数之和 =
S(1) = (n-1) + 1能被拆分成不同的整数之和
S(2) = (n-2) + 2能被拆分成不同的整数之和
。。。
S(n-1) = (n-1)能被拆分成不同的整数之和
最后一步:求并集
S(n) = Union( S(1), S(2), S(3), ..., S(n-1) )
=========================================
手动模拟一下这个算法:
n=6 能被拆分成不同的整数之和
5 + 1能被拆分成不同的整数之和 => S1 = [5,1]
4 + 2能被拆分成不同的整数之和 => S2 = [4,2]
3 + 3能被拆分成不同的整数之和
这一步要递归
3能被拆分成不同的整数之和
= 2 + 1能被拆分成不同的整数之和 => [2,1]
= 1 + 2能被拆分成不同的整数之和 => 重复
=>S3 = [3,2,1]
2 + 4能被拆分成不同的整数之和,重复,S4=[]
1 + 5能被拆分成不同的整数之和,重复,S5=[]
S = Union( S1, S2, S3, S(4), S(5) )
= [[5,1], [4,2], [3,2,1]]
=========================================
最后就是代码啦,python实现的
有2个函数,NumberSplit计算所有的拆分,checkuniq用来去重复的,去重复用了点python技巧,C++的话用hash_set应该也可以。
def NumberSplit( n ):
if n<0:
raise Exception
if n<3:
return [[n]]
sumArray = list()
for i in range(1,n):
t = NumberSplit(n-i)
for item in t:
if i in item:
continue
item.append(i)
sumArray.append(item)
return sumArray
def checkuniq(x):
for item in x:
item.sort()
return list(set(map(tuple, x)))
========================
试一下结果:
>>> checkuniq(NumberSplit(9))
[(1, 3, 5), (2, 7), (2, 3, 4), (1, 2, 6), (1, 8)]
整个大点的数字,呵呵有点慢,没有优化。
>>> g=checkuniq(NumberSplit(20))
>>> g.sort()
[(1, 2, 3, 4, 10), (1, 2, 3, 5, 9), (1, 2, 3, 6, 8), (1, 2, 3, 14), (1, 2, 4, 5, 8), (1, 2, 4, 6, 7), (1, 2, 4, 13), (1, 2, 5, 12), (1, 2, 6, 11), (1, 2, 7, 10), (1, 2, 8, 9), (1, 2, 17), (1, 3, 4, 5, 7), (1, 3, 4, 12), (1, 3, 5, 11), (1, 3, 6, 10), (1, 3, 7, 9), (1, 3, 16), (1, 4, 5, 10), (1, 4, 6, 9), (1, 4, 7, 8), (1, 4, 15), (1, 5, 6, 8), (1, 5, 14), (1, 6, 13), (1, 7, 12), (1, 8, 11), (1, 9, 10), (1, 19), (2, 3, 4, 5, 6), (2, 3, 4, 11), (2, 3, 5, 10), (2, 3, 6, 9), (2, 3, 7, 8), (2, 3, 15), (2, 4, 5, 9), (2, 4, 6, 8), (2, 4, 14), (2, 5, 6, 7), (2, 5, 13), (2, 6, 12), (2, 7, 11), (2, 8, 10), (2, 18)]
❷ 如何应付不知名的爬虫骚扰
一、手工识别和拒绝爬虫的访问
有相当多的爬虫对网站会造成非常高的负载,因此识别爬虫的来源IP是很容易的事情。最简单的办法就是用netstat检查80端口的连接:
C代码 netstat -nt | grep youhostip:80 | awk '{print $5}' | awk -F":" '{print $1}'| sort | uniq -c | sort -r -n netstat -nt | grep youhostip:80 | awk '{print $5}' | awk -F":" '{print $1}'| sort | uniq -c | sort -r -n
这行shell可以按照80端口连接数量对来源IP进行排序,这样可以直观的判断出来网页爬虫。一般来说爬虫的并发连接非常高。
如果使用lighttpd做Web Server,那么就更简单了。lighttpd的mod_status提供了非常直观的并发连接的信息,包括每个连接的来源IP,访问的URL,连接状态和连接时间等信息,只要检查那些处于handle-request状态的高并发IP就可以很快确定爬虫的来源IP了。
拒绝爬虫请求既可以通过内核防火墙来拒绝,也可以在web server拒绝,比方说用iptables拒绝:
C代码 iptables -A INPUT -i eth0 -j DROP -p tcp --dport 80 -s 84.80.46.0/24 iptables -A INPUT -i eth0 -j DROP -p tcp --dport 80 -s 84.80.46.0/24
直接封锁爬虫所在的C网段地址。这是因为一般爬虫都是运行在托管机房里面,可能在一个C段里面的多台服务器上面都有爬虫,而这个C段不可能是用户宽带上网,封锁C段可以很大程度上解决问题。
有些人提出一种脑残的观点,说我要惩罚这些爬虫。我专门在网页里面设计动态循环链接页面,让爬虫掉进陷阱,死循环爬不出来,其实根本用不着设置陷阱,弱智爬虫对正常网页自己就爬不出来,这样做多此一举不说,而且会让真正的搜索引擎降低你的网页排名。而且运行一个爬虫根本不消耗什么机器资源,相反,真正宝贵的是你的服务器CPU资源和服务器带宽,简单的拒绝掉爬虫的请求是反爬虫最有效的策略。
二、通过识别爬虫的User-Agent信息来拒绝爬虫
有很多爬虫并不会以很高的并发连接爬取,一般不容易暴露自己;有些爬虫的来源IP分布很广,很难简单的通过封锁IP段地址来解决问题;另外还有很多各种各样的小爬虫,它们在尝试Google以外创新的搜索方式,每个爬虫每天爬取几万的网页,几十个爬虫加起来每天就能消耗掉上百万动态请求的资源,由于每个小爬虫单独的爬取量都很低,所以你很难把它从每天海量的访问IP地址当中把它准确的挖出来。
这种情况下我们可以通过爬虫的User-Agent信息来识别。每个爬虫在爬取网页的时候,会声明自己的User-Agent信息,因此我们就可以通过记录和分析User-Agent信息来挖掘和封锁爬虫。我们需要记录每个请求的User-Agent信息,对于Rails来说我们可以简单的在app/controllers/application.rb里面添加一个全局的before_filter,来记录每个请求的User-Agent信息:
Ruby代码 logger.info "HTTP_USER_AGENT #{request.env["HTTP_USER_AGENT"]}" logger.info "HTTP_USER_AGENT #{request.env["HTTP_USER_AGENT"]}"
然后统计每天的proction.log,抽取User-Agent信息,找出访问量最大的那些User-Agent。要注意的是我们只关注那些爬虫的User-Agent信息,而不是真正浏览器User-Agent,所以还要排除掉浏览器User-Agent,要做到这一点仅仅需要一行shell:
Ruby代码 grep HTTP_USER_AGENT proction.log | grep -v -E 'MSIE|Firefox|Chrome|Opera|Safari|Gecko' | sort | uniq -c | sort -r -n | head -n 100 > bot.log grep HTTP_USER_AGENT proction.log | grep -v -E 'MSIE|Firefox|Chrome|Opera|Safari|Gecko' | sort | uniq -c | sort -r -n | head -n 100 > bot.log
统计结果类似这样:
C代码 57335 HTTP_USER_AGENT Baispider+(+ http://www..com/search/spider.htm)56639 HTTP_USER_AGENT Mozilla/5.0 (compatible; Googlebot/2.1; + http://www.google.com/bot.html)42610 HTTP_USER_AGENT Mediapartners-Google 19131 HTTP_USER_AGENT msnbot/2.0b (+ http://search.msn.com/msnbot.htm)57335 HTTP_USER_AGENT Baispider+(+ http://www..com/search/spider.htm) 56639 HTTP_USER_AGENT Mozilla/5.0 (compatible; Googlebot/2.1; + http://www.google.com/bot.html) 42610 HTTP_USER_AGENT Mediapartners-Google 19131 HTTP_USER_AGENT msnbot/2.0b (+ http://search.msn.com/msnbot.htm)
从日志就可以直观的看出每个爬虫的请求次数。要根据User-Agent信息来封锁爬虫是件很容易的事情,lighttpd配置如下:
C代码 $HTTP["useragent"] =~ "qihoobot|^Java|Commons-HttpClient|Wget|^php|Ruby|Python" { url.rewrite = ( "^/(.*)" => "/crawler.html" ) } $HTTP["useragent"] =~ "qihoobot|^Java|Commons-HttpClient|Wget|^PHP|Ruby|Python" { url.rewrite = ( "^/(.*)" => "/crawler.html" ) }
使用这种方式来封锁爬虫虽然简单但是非常有效,除了封锁特定的爬虫,还可以封锁常用的编程语言和HTTP类库的User-Agent信息,这样就可以避免很多无谓的程序员用来练手的爬虫程序对网站的骚扰。
还有一种比较常见的情况,就是某个搜索引擎的爬虫对网站爬取频率过高,但是搜索引擎给网站带来了很多流量,我们并不希望简单的封锁爬虫,仅仅是希望降低爬虫的请求频率,减轻爬虫对网站造成的负载,那么我们可以这样做:
C代码 $HTTP["user-agent"] =~ "Baispider+" { connection.delay-seconds = 10 } $HTTP["user-agent"] =~ "Baispider+" { connection.delay-seconds = 10 }
对网络的爬虫请求延迟10秒钟再进行处理,这样就可以有效降低爬虫对网站的负载了。
三、通过网站流量统计系统和日志分析来识别爬虫
有些爬虫喜欢修改User-Agent信息来伪装自己,把自己伪装成一个真实浏览器的User-Agent信息,让你无法有效的识别。这种情况下我们可以通过网站流量系统记录的真实用户访问IP来进行识别。
主流的网站流量统计系统不外乎两种实现策略:一种策略是在网页里面嵌入一段js,这段js会向特定的统计服务器发送请求的方式记录访问量;另一种策略是直接分析服务器日志,来统计网站访问量。在理想的情况下,嵌入js的方式统计的网站流量应该高于分析服务器日志,这是因为用户浏览器会有缓存,不一定每次真实用户访问都会触发服务器的处理。但实际情况是,分析服务器日志得到的网站访问量远远高于嵌入js方式,极端情况下,甚至要高出10倍以上。
现在很多网站喜欢采用awstats来分析服务器日志,来计算网站的访问量,但是当他们一旦采用Google Analytics来统计网站流量的时候,却发现GA统计的流量远远低于awstats,为什么GA和awstats统计会有这么大差异呢?罪魁祸首就是把自己伪装成浏览器的网络爬虫。这种情况下awstats无法有效的识别了,所以awstats的统计数据会虚高。
其实作为一个网站来说,如果希望了解自己的网站真实访问量,希望精确了解网站每个频道的访问量和访问用户,应该用页面里面嵌入js的方式来开发自己的网站流量统计系统。自己做一个网站流量统计系统是件很简单的事情,写段服务器程序响应客户段js的请求,分析和识别请求然后写日志的同时做后台的异步统计就搞定了。
通过流量统计系统得到的用户IP基本是真实的用户访问,因为一般情况下爬虫是无法执行网页里面的js代码片段的。所以我们可以拿流量统计系统记录的IP和服务器程序日志记录的IP地址进行比较,如果服务器日志里面某个IP发起了大量的请求,在流量统计系统里面却根本找不到,或者即使找得到,可访问量却只有寥寥几个,那么无疑就是一个网络爬虫。
分析服务器日志统计访问最多的IP地址段一行shell就可以了:
C代码 grep Processing proction.log | awk '{print $4}' | awk -F'.' '{print $1"."$2"."$3".0"}' | sort | uniq -c | sort -r -n | head -n 200 > stat_ip.log grep Processing proction.log | awk '{print $4}' | awk -F'.' '{print $1"."$2"."$3".0"}' | sort | uniq -c | sort -r -n | head -n 200 > stat_ip.log
然后把统计结果和流量统计系统记录的IP地址进行对比,排除真实用户访问IP,再排除我们希望放行的网页爬虫,比方Google,网络,微软msn爬虫等等。最后的分析结果就就得到了爬虫的IP地址了。以下代码段是个简单的实现示意:
Ruby代码 whitelist = [] IO.foreach("#{RAILS_ROOT}/lib/whitelist.txt") { |line| whitelist << line.split[0].strip if line } realiplist = [] IO.foreach("#{RAILS_ROOT}/log/visit_ip.log") { |line| realiplist << line.strip if line } iplist = [] IO.foreach("#{RAILS_ROOT}/log/stat_ip.log") do |line| ip = line.split[1].strip iplist << ip if line.split[0].to_i > 3000 && !whitelist.include?(ip) && !realiplist.include?(ip) end Report.deliver_crawler(iplist) whitelist = [] IO.foreach("#{RAILS_ROOT}/lib/whitelist.txt") { |line| whitelist << line.split[0].strip if line } realiplist = [] IO.foreach("#{RAILS_ROOT}/log/visit_ip.log") { |line| realiplist << line.strip if line } iplist = [] IO.foreach("#{RAILS_ROOT}/log/stat_ip.log") do |line| ip = line.split[1].strip iplist << ip if line.split[0].to_i > 3000 && !whitelist.include?(ip) && !realiplist.include?(ip) end Report.deliver_crawler(iplist)
分析服务器日志里面请求次数超过3000次的IP地址段,排除白名单地址和真实访问IP地址,最后得到的就是爬虫IP了,然后可以发送邮件通知管理员进行相应的处理。
四、网站的实时反爬虫防火墙实现策略
通过分析日志的方式来识别网页爬虫不是一个实时的反爬虫策略。如果一个爬虫非要针对你的网站进行处心积虑的爬取,那么他可能会采用分布式爬取策略,比方说寻找几百上千个国外的代理服务器疯狂的爬取你的网站,从而导致网站无法访问,那么你再分析日志是不可能及时解决问题的。所以必须采取实时反爬虫策略,要能够动态的实时识别和封锁爬虫的访问。
要自己编写一个这样的实时反爬虫系统其实也很简单。比方说我们可以用memcached来做访问计数器,记录每个IP的访问频度,在单位时间之内,如果访问频率超过一个阀值,我们就认为这个IP很可能有问题,那么我们就可以返回一个验证码页面,要求用户填写验证码。如果是爬虫的话,当然不可能填写验证码,所以就被拒掉了,这样很简单就解决了爬虫问题。
用memcache记录每个IP访问计数,单位时间内超过阀值就让用户填写验证码,用Rails编写的示例代码如下:
Ruby代码 ip_counter = Rails.cache.increment(request.remote_ip) if !ip_counter Rails.cache.write(request.remote_ip, 1, :expires_in => 30.minutes) elsif ip_counter > 2000 render :template => 'test', :status => 401 and return false end ip_counter = Rails.cache.increment(request.remote_ip) if !ip_counter Rails.cache.write(request.remote_ip, 1, :expires_in => 30.minutes) elsif ip_counter > 2000 render :template => 'test', :status => 401 and return false end
这段程序只是最简单的示例,实际的代码实现我们还会添加很多判断,比方说我们可能要排除白名单IP地址段,要允许特定的User-Agent通过,要针对登录用户和非登录用户,针对有无referer地址采取不同的阀值和计数加速器等等。
此外如果分布式爬虫爬取频率过高的话,过期就允许爬虫再次访问还是会对服务器造成很大的压力,因此我们可以添加一条策略:针对要求用户填写验证码的IP地址,如果该IP地址短时间内继续不停的请求,则判断为爬虫,加入黑名单,后续请求全部拒绝掉。为此,示例代码可以改进一下:
Ruby代码 before_filter :ip_firewall, :except => :test def ip_firewall render :file => "#{RAILS_ROOT}/public/403.html", :status => 403 if BlackList.include?(ip_sec) end before_filter :ip_firewall, :except => :test def ip_firewall render :file => "#{RAILS_ROOT}/public/403.html", :status => 403 if BlackList.include?(ip_sec) end
我们可以定义一个全局的过滤器,对所有请求进行过滤,出现在黑名单的IP地址一律拒绝。对非黑名单的IP地址再进行计数和统计:
Ruby代码 ip_counter = Rails.cache.increment(request.remote_ip) if !ip_counter Rails.cache.write(request.remote_ip, 1, :expires_in => 30.minutes) elsif ip_counter > 2000 crawler_counter = Rails.cache.increment("crawler/#{request.remote_ip}") if !crawler_counter Rails.cache.write("crawler/#{request.remote_ip}", 1, :expires_in => 10.minutes) elsif crawler_counter > 50 BlackList.add(ip_sec) render :file => "#{RAILS_ROOT}/public/403.html", :status => 403 and return false end render :template => 'test', :status => 401 and return false end ip_counter = Rails.cache.increment(request.remote_ip) if !ip_counter Rails.cache.write(request.remote_ip, 1, :expires_in => 30.minutes) elsif ip_counter > 2000 crawler_counter = Rails.cache.increment("crawler/#{request.remote_ip}") if !crawler_counter Rails.cache.write("crawler/#{request.remote_ip}", 1, :expires_in => 10.minutes) elsif crawler_counter > 50 BlackList.add(ip_sec) render :file => "#{RAILS_ROOT}/public/403.html", :status => 403 and return false end render :template => 'test', :status => 401 and return false end
如果某个IP地址单位时间内访问频率超过阀值,再增加一个计数器,跟踪他会不会立刻填写验证码,如果他不填写验证码,在短时间内还是高频率访问,就把这个IP地址段加入黑名单,除非用户填写验证码激活,否则所有请求全部拒绝。这样我们就可以通过在程序里面维护黑名单的方式来动态的跟踪爬虫的情况,甚至我们可以自己写个后台来手工管理黑名单列表,了解网站爬虫的情况。
这个策略已经比较智能了,但是还不够好!我们还可以继续改进:
1、用网站流量统计系统来改进实时反爬虫系统
还记得吗?网站流量统计系统记录的IP地址是真实用户访问IP,所以我们在网站流量统计系统里面也去操作memcached,但是这次不是增加计数值,而是减少计数值。在网站流量统计系统里面每接收到一个IP请求,就相应的cache.decrement(key)。所以对于真实用户的IP来说,它的计数值总是加1然后就减1,不可能很高。这样我们就可以大大降低判断爬虫的阀值,可以更加快速准确的识别和拒绝掉爬虫。
2、用时间窗口来改进实时反爬虫系统
爬虫爬取网页的频率都是比较固定的,不像人去访问网页,中间的间隔时间比较无规则,所以我们可以给每个IP地址建立一个时间窗口,记录IP地址最近12次访问时间,每记录一次就滑动一次窗口,比较最近访问时间和当前时间,如果间隔时间很长判断不是爬虫,清除时间窗口,如果间隔不长,就回溯计算指定时间段的访问频率,如果访问频率超过阀值,就转向验证码页面让用户填写验证码。
最终这个实时反爬虫系统就相当完善了,它可以很快的识别并且自动封锁爬虫的访问,保护网站的正常访问。不过有些爬虫可能相当狡猾,它也许会通过大量的爬虫测试来试探出来你的访问阀值,以低于阀值的爬取速度抓取你的网页,因此我们还需要辅助第3种办法,用日志来做后期的分析和识别,就算爬虫爬的再慢,它累计一天的爬取量也会超过你的阀值被你日志分析程序识别出来。
总之我们综合运用上面的四种反爬虫策略,可以很大程度上缓解爬虫对网站造成的负面影响,保证网站的正常访问。
❸ 从数据库查询对象返回一个list集合跟返回一个Object[]对象集合有什么区别阿 为什么que
前一个是一个结果集,后一个只是一个其中的一条记录的对象,用前一个方法再加上遍历就能获取所有返回对象
❹ TypeScript 类型挑战 Medium
[[toc]]
Medium , #infer , #built-in
实现 TS 内置的 ReturnType<T> ,但不可以使用它。
答案
Medium , #union , #built-in
不使用 Omit 实现 TypeScript 的 Omit<T, K> 泛型。
Omit 会创建一个省略 K 中字段的 T 对象。
答案
Medium , #readonly , #object-keys
实现一个通用 MyReadonly2<T, K> ,它带有两种类型的参数 T 和 K 。
K 指定应设置为Readonly的 T 的属性集。如果未提供 K ,则应使所有属性都变为只读,就像普通的 Readonly<T> 一样。
答案
Medium , #readonly , #object-keys , #deep
实现一个通用的 DeepReadonly<T> ,它将对象的每个参数及其子对象递归地设为只读。
您可以假设在此挑战中我们仅处理对象。数组,函数,类等都无需考虑。但是,您仍然可以通过覆盖尽可能多的不同案例来挑战自己。
答案
Medium , #infer , #tuple , #union
实现泛型 TupleToUnion<T> ,它返回元组所有值的合集。
答案
Medium , #application
在 JavaScript 中我们很常会使用可串联(Chainable/Pipeline)的函数构造一个对象,但在 TypeScript 中,你能合理的给他附上类型吗?
在这个挑战中,你可以使用任意你喜欢的方式实现这个类型 - Interface, Type 或 Class 都行。你需要提供两个函数 option(key, value) 和 get() 。在 option 中你需要使用提供的 key 和 value 扩展当前的对象类型,通过 get 获取最终结果。
你只需要在类型层面实现这个功能 - 不需要实现任何 TS/JS 的实际逻辑。
你可以假设 key 只接受字符串而 value 接受任何类型,你只需要暴露它传递的类型而不需要进行任何处理。同样的 key 只会被使用一次。
答案
Medium , #array
实现一个通用 Last<T> ,它接受一个数组 T 并返回其最后一个元素的类型。
答案
Medium , #array
实现一个通用 Pop<T> ,它接受一个数组 T 并返回一个没有最后一个元素的数组。
额外 :同样,您也可以实现 Shift , Push 和 Unshift 吗?
答案
Medium , #array , #built-in
键入函数 PromiseAll ,它接受PromiseLike对象数组,返回值应为 Promise<T> ,其中 T 是解析的结果数组。
答案
Medium , #union , `#map
有时,您可能希望根据某个属性在联合类型中查找类型。
在此挑战中,我们想通过在联合类型 Cat | Dog 中搜索公共 type 字段来获取相应的类型。换句话说,在以下示例中,我们期望 LookUp<Dog | Cat, 'dog'> 获得 Dog , LookUp<Dog | Cat, 'cat'> 获得 Cat 。
答案
Medium , #template-literal
实现 TrimLeft<T> ,它接收确定的字符串类型并返回一个新的字符串,其中新返回的字符串删除了原字符串开头的空白字符串。
答案
Medium , #template-literal
实现 Trim<T> ,它是一个字符串类型,并返回一个新字符串,其中两端的空白符都已被删除。
答案
Medium , #template-literal
实现 Capitalize<T> 它将字符串的第一个字母转换为大写,其余字母保持原样。
答案
Medium , #template-iteral
实现 Replace<S, From, To> 将字符串 S 中的第一个子字符串 From 替换为 To 。
答案
Medium , #template-literal
实现 ReplaceAll<S, From, To> 将一个字符串 S 中的所有子字符串 From 替换为 To 。
答案
Medium , #arguments
实现一个泛型 AppendArgument<Fn, A> ,对于给定的函数类型 Fn ,以及一个任意类型 A ,返回一个新的函数 G 。 G 拥有 Fn 的所有参数并在末尾追加类型为 A 的参数。
答案
Medium , #union
实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
答案
https://github.com/type-challenges/type-challenges/issues/614
Note
Medium , #template-literal
计算字符串的长度,类似于 String#length 。
答案
Medium , #array
在这个挑战中,你需要写一个接受数组的类型,并且返回扁平化的数组类型。
答案
Medium , #object-keys
实现一个为接口添加一个新字段的类型。该类型接收三个参数,返回带有新字段的接口类型。
答案
Medium , #math , #template-literal
实现一个接收string,number或bigInt类型参数的 Absolute 类型,返回一个正数字符串。
答案
Medium , #union , #string
实现一个将接收到的String参数转换为一个字母Union的类型。
答案
Medium , #object
实现联合类型的全排列,将联合类型转换成所有可能的全排列数组的联合类型。
答案
Medium , #
FooBarBaz -> foo-bar-baz
答案
Medium , #object
获取两个接口类型中的差值属性。
答案
Medium , #array
在类型系统中实现类似于 Python 中 any 函数。类型接收一个数组,如果数组中任一个元素为真,则返回 true ,否则返回 false 。如果数组为空,返回 false 。
答案
Medium , #union , #utils
实现 IsNever 类型, 解析输入 T 类型为 never 返回 true 否则 返回 false
答案
Medium , #union , #utils
实现 IsUnion 类型, 解析输入 T 类型为联合类型 返回 true 否则 返回 false
答案
Medium
实现 ReplaceKeys 类型, 它将替换联合类型中类型的键值, 如果该类型没有这个Key则跳过,如果有则替换。
答案
Medium
从对象类型中排除索引签名。
答案
https://github.com/type-challenges/type-challenges/issues/3542
Medium
实现类型 PercentageParser。根据规则 /^(+|-)?(d*)?(\%)?$/ 匹配类型 T。
匹配的结果由三部分组成,分别是:[ 正负号 , 数字 , 单位 ],如果没有匹配,则默认是空字符串。
答案
Medium
从字符串中剔除指定字符。
答案
Medium , Math
给定一个正整数作为类型的参数,要求返回的类型是该数字减 1。
答案
Medium , object
从 F 中选出类型相同的属性
答案
Medium , #object
保留没有在U中指定的类型的字段
答案
Medium , #template-literal
实现 StartsWith<T, U> ,接收两个string类型参数,然后判断 T 是否以 U 开头,根据结果返回 true 或 false
答案
Medium , #object
实现一个通用的 PartialByKeys<T, K> ,它接收两个类型参数 T 和 K 。
K 指定应设置为可选的 T 的属性集。当没有提供 K 时,它就和普通的 Partial<T> 一样使所有属性都是可选的。
答案
Medium , #object
实现一个通用的 RequiredByKeys<T, K> ,它接收两个类型参数 T 和 K 。
K 指定应设为必选的 T 的属性集。当没有提供 K 时,它就和普通的 Required<T> 一样使所有的属性成为必选的。
答案
Medium , #readonly , object-keys
实现一个通用的类型 Mutable<T> ,使类型 T 的全部属性可变(非只读)。
答案
Medium , #object
1
答案
Medium
给定只包含字符串的元组,和类型U, 递归构建对象
答案
Medium , #tuple
实现类型版本的数组反转 Array.reverse
答案
Medium , #arguments
实现类型版本的 lodash _.flip 函数
类型 FlipArguments<T> 需要函数 T 并返回一个新的函数类型。这个函数类型拥有相同的参数,但参数类型是被反转的。
答案
Medium , #array
按深度递归展平阵列。
答案
Medium
块、元素、修饰符方法 (BEM) 是 CSS 中类的流行命名约定。例如,块组件将表示为 btn ,依赖于块的元素将表示为 btn__price ,改变块样式的修饰符将表示为 btn--big 或 btn__price--warning 。实现 BEM<B, E, M> 从这三个参数生成字符串联合。其中 B 是字符串文字,E 和 M 是字符串数组(可以为空)。
答案
Medium , #object
实现二叉树中序遍历的类型版本。
答案
Medium
实现类型 just-flip-object :
答案
Medium
实现泛型 Fibonacci<T> 传入数字 T 返回正确的 Fibonacci number .
1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, ...
答案
Medium
实现类型 AllCombinations<S> 返回所有字符组合.
答案
Medium , #array
实现类型 GreaterThan<T, U> 来比较大小,就像 T > U 。不需要考虑负数
1
答案
Medium , #tuple
实现 Zip<T, U> 类型。 T, U 必须为 Tuple
答案
Medium , #tuple
实现 IsTuple , 接收类型 T 判断 T 是否为元组类型
答案
Medium , #tuple
实现 Chunk<T, N> , 它有两个必填的类型参数, T 必须为 tuple , N 必须为大于1的数字
答案
Medium , tuple
Fill , 一个常用的 JavaScript 函数, 我们用类型实现它. Fill<T, N, Start?, End?> , 它接收4个类型参数, T , N 是必填参数 T 为元组, N 为 any, Start , End 是可选参数,为大于零的数子.
为了模拟真实的功能,测试中可能会包含一些边界条件,希望大家喜欢:)
答案
Medium
实现 TrimRight<T> 它采用精确的字符串类型并返回一个删除了空格结尾的新字符串。
答案
Medium , #union , #array
实现一个像 Lodash.without 函数一样的泛型 Without<T, U>,它接收数组类型的 T 和数字或数组类型的 U 为参数,会返回一个去除 U 中元素的数组 T。
答案
Medium , template-literal
实现类型版本的 Math.trunc . 它接受字符串或数字返回整数部分,提出小数部分
答案
Medium , #array
实现类型版本的 Array.indexOf<T, U> , 它接收数组T 和 U 返回U在T中的索引值
答案
Medium , #array
实现类型版 Array.join<T, U> 接收数组T和字符串或数字 U
答案
Medium , #array
实现类型版本的 Array.lastIndexOf<T, U> , 它接收数组T 和 U 返回U在T中的反向索引值
答案
Medium , #array
实现类型版本的 Lodash.uniq , 它接收数组T,返回去重后的T
答案
Medium
实现 MapTypes<T, R> 它将对象 T 中的类型转换为类型 R 定义的不同类型,类型 R 具有以下结构。
答案
Medium , #tuple
构造一个给定长度的元组
答案
Medium
有时我们想限制数字的范围......例如。
答案
Medium , #array , #application , #string
给定一个字符串数组,进行置换和组合。它对于像video controlsList这样的类型也很有用
答案
Medium , #union
给定一个唯一元素数组,返回所有可能的子序列。
子序列是一个序列,可以通过删除一些元素或不删除任何元素而从数组中派生,而不改变其余元素的顺序。
答案
❺ 关于用python计算竖乘的问题,具体要求和希望输出格式如下
草稿版
#coding:utf-8
'''
***
x***
------------
****
****
****
------------
******
eachstartisanumber;
sumforeachlineshallbesame
'''
importrandomasRND
defNumberListFactory(width=3):
standard=range(10)
ret=[]
foriinxrange(0,width):
ifi==0:
value=standard.pop(RND.randint(1,len(standard)-1))
else:
value=standard.pop(RND.randint(0,len(standard)-1))
ret.append(value)
returnret
defNumber2List(num):
ret=[]
tmp=0
foriinxrange(len(str(num))-1,0,-1):
key=(num-tmp)/(10**i)
ret.append(key)
tmp=tmp+key*(10**i)
ret.append(num-tmp)
returnret
defList2Number(lst):
ret=0
foriinxrange(0,len(lst)):
ret+=lst[i]*(10**(len(lst)-i-1))
returnret
defList2String(lst):
return''.join([str(i)foriinlst])
defIsUniq(lst):
foriinlst:
tmp=lst[:]
tmp.remove(i)
ifiintmp:
returnFalse
returnTrue
counter=0
result=None
whileresultisNone:
counter+=1
p1=NumberListFactory()
p2=NumberListFactory()
standard=sum(p1)
ifstandard!=sum(p2):
continue
else:
multiResult=[]
foriinxrange(len(p2)-1,-1,-1):
tmp=Number2List(p2[i]*List2Number(p1))
iflen(tmp)!=4:#
continue
else:
ifIsUniq(tmp):
multiResult.append(tmp)
#filterresultwhenzero
iflen(multiResult)!=3:
continue
#
flag=True
forjinmultiResult:
ifstandard!=sum(j):
flag=False
break
ifflagisFalse:
continue
#
result=Number2List(List2Number(p1)*List2Number(p2))
iflen(result)!=6orstandard!=sum(result)orIsUniq(result)isFalse:
result=None
continue
else:
print'SUMofLine->{}'.format(standard)
print'LoopID:{} '.format(counter)
print'{}'.format(List2String(p1))
print'x{}'.format(List2String(p2))
print'-'*12
forkinxrange(len(multiResult)-1,-1,-1):
print'{}{}'.format(''*k*2,List2String(multiResult[len(multiResult)-1-k]))
print'-'*12
printList2String(result)
print' Over'
可以的话,做一些优化。
❻ python运维自动化取页面数据
1、linux系统基础,这个不用说了,是基础中的基础,连这个都不会就别干了,参考书籍,可以看鸟哥linux基础篇,至少要掌握这书60%内容,没必须全部掌握,但基本命令总得会吧
2、网络服务,服务有很多种,每间公司都会用到不同的,但基础的服务肯定要掌握,如FTP, DNS,SAMBA, 邮件, 这几个大概学一下就行,LAMP和LNMP是必须要熟练,我所指的不是光光会搭建,而是要很熟悉里面的相当配置才行,因为公司最关键的绝对是WEB服务器,所以nginx和apache要熟悉,特别是nginx一定要很熟悉才行,至少有些公司还会用tomcat,这个也最好学一下。其实网络服务方面不用太担心,一般公司的环境都已经搭建好,就算有新服务器或让你整改,公司会有相应的文档让你参照来弄,不会让你乱来的,但至少相关的配置一定要学熟,而且肯定是编译安装多,那些模块要熟悉一下他的作用,特别是PHP那些模块。
这面2点只是基础,也是必要条件,不能说是工具,下以才是真正的要掌握的工具。
3、shell脚本和另一个脚本语言,shell是运维人员必须具备的,不懂这个连入职都不行,至少也要写出一些系统管理脚本,最简单也得写个监控CPU,内存比率的脚本吧,这是最最最基本了,别以为会写那些猜数字和计算什么数的,这些没什么作用,只作学习意义,写系统脚本才是最有意义,而另一个脚本语言是可选的,一般是3P,即python, perl和php,php就不需要考虑了,除非你要做开发,我个人建议学python会比较好,难实现自动化运维,perl是文本处理很强大,反正这两个学一个就行了。
4、sed和awk工具,必须要掌握,在掌握这两个工具同时,还要掌握正则表达式,这个就痛苦了,正则是最难学的表达式,但结合到sed和awk中会很强大,在处理文本内容和过滤WEB内容时十分有用,不过在学shell的同时一般会经常结合用到的,所以学第3点就会顺便学第4点。
5、文本处理命令,sort , tr , cut, paste, uniq, tee等,必学,也是结合第3点时一并学习的。
6、数据库,首选mysql,别问我为什么不学sqlserver和oracle,因为linux用得最多绝对是mysql,增删改查必学,特别要学熟查,其它方面可能不太需要,因为运维人员使用最多还是查,哪些优化和开发语句不会让你弄的。
7、防火墙,不学不行,防火墙也算是个难点,说难不难,说易不易,最重要弄懂规则,如果学过CCNA的朋友可能会比较好学,因为iptables也有NAT表,原理是一样的,而FILTER表用得最多,反正不学就肯定不合格。
8、监控工具,十分十分重要,我个人建议,最好学这3个,cacti,nagios,zibbix,企业用得最多应该是nagios和 zibbix,反正都学吧,但nagios会有点难,因为会涉及到用脚本写自动监控,那个地方很难。
❼ python 怎么合并多行为一行
#readdatafromfile
withopen("data_src.txt",'rt')assrc:
data=[ln.strip()forlninsrc]
#','join
withopen("data_sto.txt",'wt')assto:
sto.write(','.join(list(set(data))))
python 中 set 是 “unordered collection of unique elements” 可以自动实现剔除重复数据。
❽ python编程的题目,应该怎么做啊谢谢了!问题描述如下。
用字典统计每个字符出现的次数