却定是jonstew装死兔官网6574不能在收视了,首页弹出的wwWjonstew装死兔官网6574com提示框呢?

&figure&&img src=&https://pic1.zhimg.com/v2-4c0a8b1d6ffe4cf31c127b_b.jpg& data-rawwidth=&490& data-rawheight=&187& class=&origin_image zh-lightbox-thumb& width=&490& data-original=&https://pic1.zhimg.com/v2-4c0a8b1d6ffe4cf31c127b_r.jpg&&&/figure&&p&&b&1.冒泡排序&/b&&/p&&p&冒泡排序重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。&br&这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名。&br&&/p&&p&步骤:&/p&&p&&br&&/p&&ol&&li&比较相邻的元素。如果第一个比第二个大,就交换他们两个。&br&&/li&&li&对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。&br&&/li&&li&针对所有的元素重复以上的步骤,除了最后一个。&br&&/li&&li&持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。&br&&/li&&/ol&&p&&br&&/p&&p&代码实现:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def bubble_sort(list):
length=len(list)
for index in range(length):
for i in range(1,length-index):
if list[i-1]&list[i]:
list[i],list[i-1]=list[i-1],list[i]
return list
#一下为测试其正确性:
list=[10,23,1,53,654,54,16,646,65,]
print bubble_sort(list)
&/code&&/pre&&/div&&p&&b&2.选择排序&/b&&/p&&p&从待排序的&a href=&http://link.zhihu.com/?target=http%3A//baike.baidu.com/view/38785.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&数据元素&/a&中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def select_sort(list):
length=len(list)
for index in range(length):
for i in range(index,length):
if list[index]&list[i]:
list[index],list[i]=list[i],list[index]
return list
list=[10,23,1,53,654,54,16,646,65,]
print select_sort(list)
&/code&&/pre&&/div&&p&&b&3.插入排序&/b&&/p&&p&每步将一个待排序的纪录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。&/p&&p&步骤:&/p&&ol&&li&从第一个元素开始,该元素可以认为已经被排序&/li&&li&取出下一个元素,在已经排序的元素序列中从后向前扫描&/li&&li&如果该元素(已排序)大于新元素,将该元素移到下一位置&/li&&li&重复步骤3,直到找到已排序的元素小于或者等于新元素的位置&/li&&li&将新元素插入到该位置后&/li&&li&重复步骤2~5&/li&&/ol&&p&&br&&/p&&p&代码实现:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def insert_sort(lists):
# 插入排序
count = len(lists)
for i in range(1, count):
key = lists[i]
while j &= 0:
if lists[j] & key:
lists[j + 1] = lists[j]
lists[j] = key
return lists
list=[10,23,1,53,654,54,16,646,65,]
print insert_sort(lists)
&/code&&/pre&&/div&&p&&br&&/p&&p&&b&4.希尔排序&/b&&/p&&p&先取一个小于n的整数d1作为第一个&a href=&http://link.zhihu.com/?target=http%3A//baike.baidu.com/view/422272.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&增量&/a&,把文件的全部记录分组。所有距离为d1的倍数的记录放在同一个组中。先在各组内进行&a href=&http://link.zhihu.com/?target=http%3A//baike.baidu.com/view/1193395.htm& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&直接插入排序&/a&;然后,取第二个增量d2&d1重复上述的分组和排序,直至所取的增量&br&&/p&&figure&&img src=&https://pic1.zhimg.com/9c63f93b1df1b9ae5af7ac_b.png& class=&content_image&&&/figure&&p&即所有记录放在同一组中进行直接插入排序为止。&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def shell_sort(list):
length=len(list)
dist=length/2
while dist&0:
for i in range(dist,length):
temp=list[i]
while j&=dist and temp&list[j-dist]:
list[j]=list[j-dist]
list[j]=temp
return list
list=[10,23,1,53,654,54,16,646,65,]
print shell_sort(list)
&/code&&/pre&&/div&&p&&b&5.归并排序&/b&&/p&&p&归并排序,就是把两个已经排列好的序列合并为一个序列。&br&&/p&&p&代码实现:&/p&&p&&br&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
#算法逻辑比较简单,以第一个list为基准,第二个向第一个插空
def merge_sort(list1,list2):
length_list1=len(list1)
length_list2=len(list2)
for i in range(length_list1):
while list2[j]&list1[i] and j&length_list2:
list3.append(list2[j])
list3.append(list1[i])
if j&(length_list2-1):
for k in range(j,length_list2):
list3.append(list2[k])
return list3
list1=[1,3,5,10]
list2=[2,4,6,8,9,11,12,13,14]
print merge_sort(list1,list2)
&/code&&/pre&&/div&&p&6.快速排序&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&随意选择一个数字作为基准,比基准数字大的在右,比基准数字小的在左。
# -*- coding:utf-8 -*-
def kp(arr,i,j):#快排总函数
#制定从哪开始快排
base=kpgc(arr,i,j)
kp(arr,i,base)
kp(arr,base+1,j)
def kpgc(arr,i,j):#快排排序过程
base=arr[i]
while i&j:
while i&j and arr[j]&=base:
while i&j and arr[j]&base:
arr[i]=arr[j]
arr[j]=arr[i]
arr[i]=base
ww=[3,2,4,1,59,23,13,1,3]
kp(ww,0,len(ww)-1)
&/code&&/pre&&/div&&p&7.堆排序&/p&&p&堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。&/p&&p&步骤:&/p&&ol&&li&创建最大堆:将堆所有数据重新排序,使其成为最大堆&/li&&li&最大堆调整:作用是保持最大堆的性质,是创建最大堆的核心子程序&/li&&li&堆排序:移除位在第一个数据的根节点,并做最大堆调整的递归运算&/li&&/ol&&p&代码实现:&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def head_sort(list):
length_list = len(list)
first=int(length_list/2-1)
for start in range(first,-1,-1):
max_heapify(list,start,length_list-1)
for end in range(length_list-1,0,-1):
list[end],list[0]=list[0],list[end]
max_heapify(list,0,end-1)
return list
def max_heapify(ary,start,end):
root = start
while True:
child = root*2 + 1
if child & end:
if child + 1 &= end and ary[child]&ary[child+1]:
child = child + 1
if ary[root]&ary[child]:
ary[root],ary[child]=ary[child],ary[root]
root=child
list=[10,23,1,53,654,54,16,646,65,]
print head_sort(list)
&/code&&/pre&&/div&&p&&b&8.计数排序&/b&&/p&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&# -*- coding:utf-8 -*-
def count_sort(list):
for i in list:
if i & min:
if i & max:
count = [0] * (max - min +1)
for j in range(max-min+1):
count[j]=0
for index in list:
count[index-min]+=1
for a in range(max-min+1):
for c in range(count[a]):
list[index]=a+min
return list
list=[10,23,1,53,654,54,16,646,65,]
print count_sort(list)
&/code&&/pre&&/div&&p&本文来源于自己刚学数据结构时的笔记,文字叙述以及代码实现思维参考了百度百科,大神&a class=&member_mention& href=&http://www.zhihu.com/people/87d0a4e5cdfff534bbabbb0& data-hash=&87d0a4e5cdfff534bbabbb0& data-hovercard=&p$b$87d0a4e5cdfff534bbabbb0&&@EINDEX&/a&
的专栏以及网上搜到的经验贴,感激ing^_^&/p&&p&&/p&
1.冒泡排序冒泡排序重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。 这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶…
&figure&&img src=&https://pic4.zhimg.com/v2-b19fedf16aa193d0aaf37a2_b.jpg& data-rawwidth=&1600& data-rawheight=&540& class=&origin_image zh-lightbox-thumb& width=&1600& data-original=&https://pic4.zhimg.com/v2-b19fedf16aa193d0aaf37a2_r.jpg&&&/figure&&blockquote&&p&本文是一系列介绍 RxJS 文章的第一篇,这一系列的文章将从一个小的例子开始,逐渐深入的讲解 RxJS 在各种场景下的应用。对应的,也会有对 RxJS 各种操作符的讲解(如果能坚持不弃坑的话。这篇文章将会用一个 Todo list 作为例子,讲解 RxJS 是如何组合各种同步/异步业务的,在这个过程中,初次接触 RxJS 的同学可能会被各种操作符和组合搞得云里雾里,但没关系,本片的主旨是让大家了解 RxJS 是如何在我们熟悉的那些业务场景中使用的,更细节的介绍将会在后续的文章中。&/p&&/blockquote&&h2&准备工作&/h2&&p&首先在 &a href=&https://link.zhihu.com/?target=https%3A//github.com/teambition/learning-rxjs& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&GitHub - teambition/learning-rxjs: Learning RxJS step by step&/a& clone 项目所需的 seed,本文中所有涉及到 RxJS 的代码将全部使用 TypeScript 编写。&/p&&p&使用 npm start 启动 seed 项目,在浏览器中通过 &i&&a href=&https://link.zhihu.com/?target=http%3A//localhost%3A3000& class=& external& target=&_blank& rel=&nofollow noreferrer&&&span class=&invisible&&http://&/span&&span class=&visible&&localhost:3000&/span&&span class=&invisible&&&/span&&/a&&/i& 进入 demo 页面,这篇文章中我们将实现以下几点功能:&/p&&ol&&li&在输入框中输入字符,在回车的时候将输入框中的文字变成一个 todo item,同时清空输入框中的内容。&/li&&li&在输入框中输入字符,点击 add 按钮,将输入框中的文字变成一个 todo item,同时清空输入框中的文字。&/li&&li&点击一个 todo item,让它变成已完成的状态&/li&&li&点击 todo item 右边的 remove button,将这个 todo item 从 todo list 中移除。&/li&&/ol&&h2&第一个 Observable&/h2&&p&如果要响应用户按下回车这个行为,我们首先要获取用户输入的事件并把它转变成 Observable,在 RxJS 中,可以直接使用 fromEvent 操作符直接将一个 eventListener 转变成一个 Observable:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// src/app.ts&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&c1&&// do 操作符一般用来处理 Observable 的副作用,例如操作 DOM,修改外部变量,打 log&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span&&span class=&p&&))&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&这样在控制台就能看到每次用户输入时对应的 event 在 input$ Observable 中流动了。&/p&&br&&figure&&img src=&https://pic4.zhimg.com/v2-2d892a45c070bf921ce47b6_b.jpg& data-rawwidth=&2548& data-rawheight=&852& class=&origin_image zh-lightbox-thumb& width=&2548& data-original=&https://pic4.zhimg.com/v2-2d892a45c070bf921ce47b6_r.jpg&&&/figure&&br&&br&&h2&使用 filter 进行数据过滤&/h2&&p&但我们并不关心用户的输入的其它值,只需要获取&b&按下回车事件&/b&这个值,并作出响应。此时我们只需要对这个 Observable 进行 filter :&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import { Observable } from 'rxjs'
const $input = &HTMLInputElement&document.querySelector('.todo-val')
const input$ = Observable.fromEvent&KeyboardEvent&($input, 'keydown')
.filter(r =& r.keyCode === 13)
.do(r =& console.log(r))
const app$ = input$
app$.subscribe()
&/code&&/pre&&/div&&figure&&img src=&https://pic3.zhimg.com/v2-68dac6e52edef82a95cbe9f_b.jpg& data-rawwidth=&2556& data-rawheight=&898& class=&origin_image zh-lightbox-thumb& width=&2556& data-original=&https://pic3.zhimg.com/v2-68dac6e52edef82a95cbe9f_r.jpg&&&/figure&&br&&br&&h2&使用 map 进行数据的变换&/h2&&p&为了完成在回车的时候将输入框中的文字变成一个 todo item,我们需要获取 input 中的值,并将它变成一个 todo-item 节点。这个过程是一个很典型的 map 的过程: &br&可以类比于 Array 的 Map : [ … KeyboardEvent ] =& [… HTMLElement ] &br&首先在输入回车的时候把 KeyboardEvent map 到 string, filter 掉空值&/p&&br&&div class=&highlight&&&pre&&code class=&language-text&&&span&&/span&import { Observable } from 'rxjs'
const $input = &HTMLInputElement&document.querySelector('.todo-val')
const input$ = Observable.fromEvent&KeyboardEvent&($input, 'keydown')
.filter(r =& r.keyCode === 13)
const app$ = input$
.map(() =& $input.value)
.filter(r =& r !== '')
.do(r =& console.log(r))
app$.subscribe()
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-ab38b01a02ac_b.jpg& data-rawwidth=&2554& data-rawheight=&648& class=&origin_image zh-lightbox-thumb& width=&2554& data-original=&https://pic1.zhimg.com/v2-ab38b01a02ac_r.jpg&&&/figure&&br&&p&再来一个 createTodoItem 的 helper:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// lib.ts&/span&
&span class=&kr&&export&/span& &span class=&kr&&const&/span& &span class=&nx&&createTodoItem&/span& &span class=&o&&=&/span& &span class=&p&&(&/span&&span class=&nx&&val&/span&&span class=&o&&:&/span& &span class=&nx&&string&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&kr&&const&/span& &span class=&nx&&result&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLLIElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&createElement&/span&&span class=&p&&(&/span&&span class=&s1&&'LI'&/span&&span class=&p&&)&/span&
&span class=&nx&&result&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&add&/span&&span class=&p&&(&/span&&span class=&s1&&'list-group-item'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&sb&&`&/span&
&span class=&sb&&
&/span&&span class=&si&&${&/span&&span class=&nx&&val&/span&&span class=&si&&}&/span&&span class=&sb&&&/span&
&span class=&sb&&
&button type=&button& class=&btn btn-default button-remove& aria-label=&right Align&&&/span&
&span class=&sb&&
&span class=&glyphicon glyphicon-remove& aria-hidden=&true&&&/span&&/span&
&span class=&sb&&
&/button&&/span&
&span class=&sb&&
&span class=&nx&&result&/span&&span class=&p&&.&/span&&span class=&nx&&innerHTML&/span& &span class=&o&&=&/span& &span class=&nx&&innerHTML&/span&
&span class=&k&&return&/span& &span class=&nx&&result&/span&
&span class=&p&&}&/span&
&/code&&/pre&&/div&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&c1&&// app.ts&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&createTodoItem&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./lib'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span&&span class=&p&&.&/span&&span class=&nx&&keyCode&/span& &span class=&o&&===&/span& &span class=&mi&&13&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span&&span class=&p&&))&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&figure&&img src=&https://pic1.zhimg.com/v2-3fc8b032cf_b.jpg& data-rawwidth=&2542& data-rawheight=&658& class=&origin_image zh-lightbox-thumb& width=&2542& data-original=&https://pic1.zhimg.com/v2-3fc8b032cf_r.jpg&&&/figure&&br&&p&将 map 出来的节点插入 DOM,顺便一提的是,在 RxJS 的范式中,数据流动中的 副作用 都应该写在 do 操作符中。&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&createTodoItem&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./lib'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$list&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLUListElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.list-group'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span&&span class=&p&&.&/span&&span class=&nx&&keyCode&/span& &span class=&o&&===&/span& &span class=&mi&&13&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span&&span class=&p&&))&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&实现到这一步,我们已经可以把输入的字符串变成一个个 item 了:&/p&&br&&p&下一步我们来实现点击 add 按钮增加一个 todo item 功能。可以看到,在程序上这个操作和按下回车后需要的后续操作是一样的。所以我们只需要将点击 add 按钮事件也变成一个 Observable 然后与 按下回车 的 Observable merge 到一起就好了:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&createTodoItem&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./lib'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$list&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLUListElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.list-group'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$add&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.button-add'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&enter$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span&&span class=&p&&.&/span&&span class=&nx&&keyCode&/span& &span class=&o&&===&/span& &span class=&mi&&13&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&clickAdd$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&MouseEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$add&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&enter$&/span&&span class=&p&&.&/span&&span class=&nx&&merge&/span&&span class=&p&&(&/span&&span class=&nx&&clickAdd$&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span&&span class=&p&&))&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&接下来在 do 操作符中把 input 中的值清除掉:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&p&&...&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span& &span class=&o&&=&/span& &span class=&s1&&''&/span&
&span class=&p&&})&/span&
&span class=&p&&...&/span&
&/code&&/pre&&/div&&h2&从 Observable mergeMap 到 新的 Observable&/h2&&p&在创建出这些 item 后,我们再给它们加上各自的 event listener 来完成 &strong&点击一个 todo item,让它变成已完成的状态&/strong& 功能,而新的 eventListener 只能在这些 item 创建出来以后加上。所以这个过程是 Observable&HTMLElement& =& map =& Observable&MouseEvent& =& merge 的过程,在 RxJS 中有一个操作符可以一步完成这个 map and merge 的过程:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&createTodoItem&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./lib'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$list&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLUListElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.list-group'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$add&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.button-add'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&enter$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span&&span class=&p&&.&/span&&span class=&nx&&keyCode&/span& &span class=&o&&===&/span& &span class=&mi&&13&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&clickAdd$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&MouseEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$add&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&enter$&/span&&span class=&p&&.&/span&&span class=&nx&&merge&/span&&span class=&p&&(&/span&&span class=&nx&&clickAdd$&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span& &span class=&o&&=&/span& &span class=&s1&&''&/span&
&span class=&p&&})&/span&
&span class=&c1&&// map and merge&/span&
&span class=&p&&.&/span&&span class=&nx&&mergeMap&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&MouseEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span& &span class=&o&&=&&/span& &span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&target&/span& &span class=&o&&===&/span& &span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&mapTo&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&$todoItem&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&contains&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&))&/span& &span class=&p&&{&/span&
&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&remove&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span& &span class=&k&&else&/span& &span class=&p&&{&/span&
&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&add&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span&&span class=&p&&))&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&blockquote&&p&因为 todoItem 上还有其它功能性的按钮,比如移除 todoItem ,所以在 mergeMap 中我们用 filter 过滤掉了非 li 标签的点击事件。同时下一个 do 操作符中需要 consume 这个 $todoItem 对象,所以我们在 filter 后将它 mapTo 下一个操作符。&/p&&/blockquote&&h2&从一个 Observable map 到不同的 Observable,share/publish 它再操作它&/h2&&p&为了实现点击 remove 按钮,把当前的 todoItem 移除,我们需要从 item$ 的 Observable 中重新 mergeMap 出新的 remove$ 的 Observable:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&Observable&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'rxjs'&/span&
&span class=&kr&&import&/span& &span class=&p&&{&/span& &span class=&nx&&createTodoItem&/span& &span class=&p&&}&/span& &span class=&nx&&from&/span& &span class=&s1&&'./lib'&/span&
&span class=&kr&&const&/span& &span class=&nx&&$input&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLInputElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.todo-val'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$list&/span& &span class=&o&&=&/span& &span class=&o&&&&/span&&span class=&nx&&HTMLUListElement&/span&&span class=&o&&&&/span&&span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.list-group'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&$add&/span& &span class=&o&&=&/span& &span class=&nb&&document&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.button-add'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&enter$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&KeyboardEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$input&/span&&span class=&p&&,&/span& &span class=&s1&&'keydown'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span&&span class=&p&&.&/span&&span class=&nx&&keyCode&/span& &span class=&o&&===&/span& &span class=&mi&&13&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&clickAdd$&/span& &span class=&o&&=&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&MouseEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$add&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&input$&/span& &span class=&o&&=&/span& &span class=&nx&&enter$&/span&&span class=&p&&.&/span&&span class=&nx&&merge&/span&&span class=&p&&(&/span&&span class=&nx&&clickAdd$&/span&&span class=&p&&)&/span&
&span class=&kr&&const&/span& &span class=&nx&&item$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span& &span class=&o&&=&/span& &span class=&s1&&''&/span&
&span class=&p&&})&/span&
&span class=&kr&&const&/span& &span class=&nx&&toggle$&/span& &span class=&o&&=&/span& &span class=&nx&&item$&/span&&span class=&p&&.&/span&&span class=&nx&&mergeMap&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&k&&return&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&o&&&&/span&&span class=&nx&&MouseEvent&/span&&span class=&o&&&&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&e&/span& &span class=&o&&=&&/span& &span class=&nx&&e&/span&&span class=&p&&.&/span&&span class=&nx&&target&/span& &span class=&o&&===&/span& &span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&mapTo&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&$todoItem&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&k&&if&/span& &span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&contains&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&))&/span& &span class=&p&&{&/span&
&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&remove&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span& &span class=&k&&else&/span& &span class=&p&&{&/span&
&span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&classList&/span&&span class=&p&&.&/span&&span class=&nx&&add&/span&&span class=&p&&(&/span&&span class=&s1&&'done'&/span&&span class=&p&&)&/span&
&span class=&p&&}&/span&
&span class=&p&&})&/span&
&span class=&kr&&const&/span& &span class=&nx&&remove$&/span& &span class=&o&&=&/span& &span class=&nx&&item$&/span&&span class=&p&&.&/span&&span class=&nx&&mergeMap&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&kr&&const&/span& &span class=&nx&&$removeButton&/span& &span class=&o&&=&/span& &span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&querySelector&/span&&span class=&p&&(&/span&&span class=&s1&&'.button-remove'&/span&&span class=&p&&)&/span&
&span class=&k&&return&/span& &span class=&nx&&Observable&/span&&span class=&p&&.&/span&&span class=&nx&&fromEvent&/span&&span class=&p&&(&/span&&span class=&nx&&$removeButton&/span&&span class=&p&&,&/span& &span class=&s1&&'click'&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&mapTo&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&$todoItem&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&c1&&// 从 DOM 上移掉 todo item&/span&
&span class=&kr&&const&/span& &span class=&nx&&$parent&/span& &span class=&o&&=&/span& &span class=&nx&&$todoItem&/span&&span class=&p&&.&/span&&span class=&nx&&parentNode&/span&
&span class=&nx&&$parent&/span&&span class=&p&&.&/span&&span class=&nx&&removeChild&/span&&span class=&p&&(&/span&&span class=&nx&&$todoItem&/span&&span class=&p&&)&/span&
&span class=&p&&})&/span&
&span class=&kr&&const&/span& &span class=&nx&&app$&/span& &span class=&o&&=&/span& &span class=&nx&&toggle$&/span&&span class=&p&&.&/span&&span class=&nx&&merge&/span&&span class=&p&&(&/span&&span class=&nx&&remove$&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&console&/span&&span class=&p&&.&/span&&span class=&nx&&log&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span&&span class=&p&&))&/span&
&span class=&nx&&app$&/span&&span class=&p&&.&/span&&span class=&nx&&subscribe&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&然而,这段代码并没有按我们预期的工作,remove button 点击之后是没有反应的。 &br&这是因为: &br&&strong&Observable 默认是 lazy 且 unioncast的,这意味着:&/strong&&/p&&ol&&li&它只有在订阅的时候才会被执行&/li&&li&它被多个订阅者订阅会执行多次,并且执行时上下文是独立的&/li&&/ol&&p&也就是说,我们的 remove$ Observable 会重新让 item$ Observable 中的逻辑重新执行一遍:&/p&&br&&figure&&img src=&https://pic4.zhimg.com/v2-ef98d1a63cd07a94a1e01d52bea8bb87_b.jpg& data-rawwidth=&1574& data-rawheight=&992& class=&origin_image zh-lightbox-thumb& width=&1574& data-original=&https://pic4.zhimg.com/v2-ef98d1a63cd07a94a1e01d52bea8bb87_r.jpg&&&/figure&&br&&p&在上图中,toggle$ Observable 先订阅并执行了黄色箭头部分的过程,remove$ Observable 订阅的时候重新执行绿色部分的过程,然而这个时候 input$ Observable 中已经不会流数据出来了。&/p&&p&想象一下,首先 toggle$ Observable 被订阅,随后 remove$ Observable 被订阅。此时由于这两个 Observable 被订阅导致 $item Observable 被订阅了&b&两次&/b&,所以对 input 与 add button 的 addEventlistener 逻辑执行了&b&两次&/b&。在按下回车或者点击 add button 的时候,第一个 item$ Observable 的订阅逻辑先执行,向 DOM 中加入了一个 todoItem 并将 input 清空,此时再执行第二个 item$ Observable 的订阅逻辑,此时 input 里面已经为空,所以这个 item$ Observable 里面没有数据流过,这也是我们的代码没有按照预期执行的原因。为了验证这个猜想,我们只需要把 $item Observable 中的 do 操作符中的&i& $&b&input.value = '' &/b&&/i&注释掉就可以更直观的观察到程序现在的运行状态了:&/p&&figure&&img src=&https://pic4.zhimg.com/v2-94eafcc2f3d4c321fa05_b.jpg& data-rawwidth=&2552& data-rawheight=&832& class=&origin_image zh-lightbox-thumb& width=&2552& data-original=&https://pic4.zhimg.com/v2-94eafcc2f3d4c321fa05_r.jpg&&&/figure&&br&&p&图中红色的箭头是 toggle$ Observable 的 subscribe 逻辑执行的结果,这个 todoItem 节点只会处理 toggle 逻辑。黄色箭头的部分是 remove$ Observable 的 subscribe 逻辑执行的结果,这个 todoItem 节点只会处理 remove 逻辑。(这也很好的证明了 Observable 是 unioncast 的特性)&/p&&p&解决的方法其实很简单,我们不想要在每次订阅的时候都重复执行 item$ Observable 的逻辑,所以只需要:&/p&&br&&div class=&highlight&&&pre&&code class=&language-js&&&span&&/span&&span class=&kr&&const&/span& &span class=&nx&&item$&/span& &span class=&o&&=&/span& &span class=&nx&&input$&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(()&/span& &span class=&o&&=&&/span& &span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&filter&/span&&span class=&p&&(&/span&&span class=&nx&&r&/span& &span class=&o&&=&&/span& &span class=&nx&&r&/span& &span class=&o&&!==&/span& &span class=&s1&&''&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&map&/span&&span class=&p&&(&/span&&span class=&nx&&createTodoItem&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&k&&do&/span&&span class=&p&&((&/span&&span class=&nx&&ele&/span&&span class=&o&&:&/span& &span class=&nx&&HTMLLIElement&/span&&span class=&p&&)&/span& &span class=&o&&=&&/span& &span class=&p&&{&/span&
&span class=&nx&&$list&/span&&span class=&p&&.&/span&&span class=&nx&&appendChild&/span&&span class=&p&&(&/span&&span class=&nx&&ele&/span&&span class=&p&&)&/span&
&span class=&nx&&$input&/span&&span class=&p&&.&/span&&span class=&nx&&value&/span& &span class=&o&&=&/span& &span class=&s1&&''&/span&
&span class=&p&&})&/span&
&span class=&p&&.&/span&&span class=&nx&&publishReplay&/span&&span class=&p&&(&/span&&span class=&mi&&1&/span&&span class=&p&&)&/span&
&span class=&p&&.&/span&&span class=&nx&&refCount&/span&&span class=&p&&()&/span&
&/code&&/pre&&/div&&p&此时的 item$ 是这样的&/p&&figure&&img src=&https://pic1.zhimg.com/v2-83e1b936dba9ea77f9449_b.jpg& data-rawwidth=&1290& data-rawheight=&1318& class=&origin_image zh-lightbox-thumb& width=&1290& data-original=&https://pic1.zhimg.com/v2-83e1b936dba9ea77f9449_r.jpg&&&/figure&&br&&br&&blockquote&&p&关于 Observable 的 &b&hot&/b& vs &b&cold&/b&, &b&Observable&/b& vs &b&Subject&/b& 等概念,以及这里为什么用 &b&publishReplay&/b&, 它的参数为什么是 1,将会在后续的章节中深入讲解,这里我们只需要关注这种行为就好了。&/p&&/blockquote&&p&自此,一个简单的 todoList 的四种需求已经被我们用 RxJS 实现了,下一篇文章我们会介绍如何用 RxJS 把网络请求,websocket 等事件接入到这些业务逻辑中。&/p&&br&&h2&广告&/h2&&p&&i&skipUntil(you are interested in TypeScript)&/i&&/p&&p&关于 TypeScript 的最佳实践,一直都有一些小伙伴问我,之前也一直没有精力做详细的回答。现在好消息来了,由我和 &a href=&https://link.zhihu.com/?target=https%3A//github.com/Davidcai1993& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&DavidCai1993 (David Cai) · GitHub&/a&, &a href=&https://link.zhihu.com/?target=https%3A//github.com/vagusX& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&vagusX (vagusX) · GitHub&/a&
翻译的 Learning TypeScript 中文版近期就会开卖了!书里面涵盖了运用面向对象的最佳实践编写可维护可扩展的 TypeScript 代码,搭建自动化的 TypeScript workflow,使用 TypeScript 进行自动化单元测试 & 集成测试,使用 TypeScript 及其最佳实践从头实现 MVC 框架 & 应用 等多个方面的内容,讲解非常详细,我的很多 TypeScript 编写习惯都是在译这本书的时候养成的,值得一看!&/p&
本文是一系列介绍 RxJS 文章的第一篇,这一系列的文章将从一个小的例子开始,逐渐深入的讲解 RxJS 在各种场景下的应用。对应的,也会有对 RxJS 各种操作符的讲解(如果能坚持不弃坑的话。这篇文章将会用一个 Todo list 作为例子,讲解 RxJS 是如何组合各种…
&figure&&img src=&https://pic4.zhimg.com/v2-e7ddaab01ef2e4f23c1a_b.jpg& data-rawwidth=&1198& data-rawheight=&721& class=&origin_image zh-lightbox-thumb& width=&1198& data-original=&https://pic4.zhimg.com/v2-e7ddaab01ef2e4f23c1a_r.jpg&&&/figure&&p&&b&(欢迎移步文章末尾看文章更新)&/b&&/p&自从2014年第一次接触到MOOC(网络公开课,对,就是可以&b&免费上&/b&的那种)之后,我的人生轨迹彻底改变了。2014年,我面试腾讯实习被拒(主要我屁都不会),2015年底,我拿到了(Facebook,Google, LinkedIn) 的offer。读master的时候,我的主攻方向是网络安全和密码学,学习的课程也主要偏数学以及各种hack黑科技,所以课堂知识并不能满足找码农工作的基本需求。这篇文章不说我,只说课,那些我上了,并且对我很有帮助的课程。&p&我是一个非常喜欢吐槽的人,在CMU上学的时候,我就经常吐槽学校老师的讲课方式(主要我傻,我学不会的就怪老师...)。而下面的这些课,我却基本找不到任何瑕疵。。。&br&&/p&&p&&b&如果你能够坚持上完这些课,那么其实我觉得你并不需要一个CS学位就能找到一个不错的CS工作!&/b&&/p&&h2&为什么要介绍国外的MOOC呢?&/h2&&p&虽然国内的CS教育进步虽快,但是国外的CS课程往往更贴实际,而且授课教师往往都同时具有很强的academic和industry的背景,所以他们不单知道怎么把知识交给你,也知道怎么让你成为一个good码农。&/p&&p&无论是CS科班,还是转专业的学生,或者是PHD,这些课都是很好的参考资料。美国大学一门课的收费在5000美元左右,所以如果真的能够把这些课上下来,相当于白赚2万多美刀。不过,这些顶级的美国大学也不是随随便便就可以进的。&/p&&p&我推荐的这几门课都属于比较早期的MOOC课程,经历过时间的验证,质量还是相当有保证的。真心的,其实很多大学的课程都不如这几门。。。&b&在CS界,其实最好的东西,往往是免费的。所以,如果大家觉得我的文章写的不好,我就转行去做收费的算法培训了!&/b&&br&&/p&&h2&找工作不是光刷题就好了吗?&/h2&&p&刷题肯定是必须的,但是要作为一个有文化有底蕴的码农,就必须有比较扎实的计算机基础。而这些是刷题无法给你的。工作以后,基础比较好的人往往会更快的发现并解决工作中的问题。这些课可以让你think like a software engineer ,让你更好的装逼。&/p&&p&这些课都配套了非常有意思的project,对于没有project可以写,背景比较薄弱的同学来说,完全是可以写到简历上的。&/p&&p&对于想来硅谷找工作的同学来说,这些课程可以让你更好的复习一些基础知识,可以使你 talk like a silicon valley engineer. 上课的时候,注意老师是怎么解释每个Topic的,注意他们是怎么举例子的,这些会提升你在面试中的交流技巧。&/p&&p&废话说了这么多,开始罗列。&/p&&h2&Udacity: Introduction to Computer Science(计算机科学导论)&/h2&&p&&a href=&https://link.zhihu.com/?target=https%3A//cn.udacity.com/course/intro-to-computer-science--cs101& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送门&/a&。Udacity的CS入门级别课,讲解的非常简单。这门课面向的对象是高中毕业生,所以不要畏难。这是Udacity上比较早期的课程。课程的&a href=&https://link.zhihu.com/?target=https%3A//cn.udacity.com/course/intro-to-computer-science--cs101& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&介绍页面&/a&写的很详细了,我就不介绍了。我上这门课的时候,udacity还没有收费服务。不过良心的是,你仍然可以免费上所有的课!&/p&&p&如果是CS科班的同学,其实可以跳过这么课,因为实在太简单了。但是对于编程技术比较薄弱(或者零基础)的同学来说,这绝对是非常适合入门的课。课程的语言为python,属于码农必会语言。现在硅谷的面试中,也有很多同学直接使用python进行面试。&/p&&p&课程虽然简单,但是这并不影响课程的价值。主要是快速入门,同时培养对计算机的兴趣。北美学校基本都会使用python作为入门语言,这样可以快速让学生上手,同时对CS产生强烈的兴趣。国内学校一般都采用C语言作为计算机入门语言,上完之后很多同学再也不想碰编程了。&/p&&h2&CS 61A: The Structure and Interpretation of Computer Programs&/h2&&p&&a href=&https://link.zhihu.com/?target=http%3A//cs61a.org/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送门&/a&。Berkeley的经典CS入门课。虽然是入门,确是非常有深度的一门课。学完之后,可以让你的python水平大涨,让你学会很多python的奇巧淫技。同时也会让你对编程语言有比较深层次的理解。虽然是python授课,但是里面的topic同样适合其他语言。上完这么课,我觉得我第一次懂得了什么是recursion,第一次懂了什么是function call。。。&/p&&p&我只听过John DeNero的版本,因为他准备的资料非常丰富。大神John DeNero,不但研究搞得好,而且工业界(Google Scientist)的经验也非常丰富。更难能可贵的是,他把所有课程的资料都放到了网上,并且每年都在更新。在这个物欲横流的社会,真的是一股清流。&/p&&p&这门课用的教材是SICP的改版。Berkeley的老师把SICP的书改写成了Python的版本,使得这本经典的CS教材更符合现代码农的需要。SICP这本书,是计算机界&b&绝对经典的著作之一(top10当之无愧),恰巧也是最薄的。&/b&跟人聊天的时候,只要提到SICP这个词,绝对让你逼格提高八度(码农界的一种装逼大法就是甩各种你没有听过的名词)。很久很久以前,我曾经尝试着读过,不是很读的下去。。。但是后来跟着这门课同步学习了这本书,受益匪浅!&/p&&h2&CS61B: Data Structures&/h2&&p&如果说非要选一门对找工作最重要的课,那么就是这一门了。如果时间不允许,只能上一门课的话,那么就上这门课了。上完这门课,你就可以刷题了。这门课选用的语言是Java,相对于C++而言,比较容易上手。&/p&&p&这门课比较流行的版本是2014 Spring的版本(&a href=&https://link.zhihu.com/?target=https%3A//people.eecs.berkeley.edu/%7Ejrs/61b/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送&/a&)。授课老师采用传统的黑板书写方式。我并没有看课程的视频,我只是反复阅读了课程的讲义,字里行间都让我受益匪浅。有基础的同学可以直接阅读讲义之后做作业!&/p&&p&我个人比较喜欢2016年Spring的版本(授课老师Josh Hug,&a href=&https://link.zhihu.com/?target=http%3A//datastructur.es/sp16/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送门&/a&),这是一个比较新的版本,所以网上上过的人并不是很多。这个版本比2014年的版本内容丰富多了,老师基本就是让学生keep implementing new things. 学生虽然被虐的很爽,但是对老师的评价确非常非常的高。Josh Hug在Berkeley 有多受欢迎呢?请看这个&a href=&https://link.zhihu.com/?target=https%3A//www.reddit.com/r/berkeley/comments/354cs5/people_in_cs61b_is_it_just_me_or_is_there_truly/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网页&/a&,Berkeley的同学在reddit上集体膜拜这个老师,有同学说:“&i&The only negative thing about Josh Hug is that he doesn't teach every course in which I am enrolled. Completely agree with your sentiments. I've never had a more dedicated and engaged professor.” &/i& 或者看这个&a href=&https://link.zhihu.com/?target=http%3A//www.ratemyprofessors.com/ShowRatings.jsp%3Ftid%3D667663& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&网页&/a&(虽然一般难的课评分不容易高,但是Josh在ratemyprofessors上的评分有4.9/5,前面提到的John DeNero也有4.7分之高)。&/p&&p&Josh经常会手把手教你好多东西。课程有两个大的project,一个是实现一个简单的Editor,一个是BearMaps(实现一个简单的Google Maps)。对新手来说,确实有一点难度,但是却可以作为简历上比较有分量的Project。这也是出了CMU之后,我第一次见到过这么接地气的Project.&/p&&p&Josh在2017(&a href=&https://link.zhihu.com/?target=http%3A//datastructur.es/sp17/& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送门&/a&)年还会继续教这么课,估计会比2016年有不少改进,不过目前还没有完全更新。&/p&&p&&b&其实很大一部分面试题都是那些经典算法的变种,所以数据结构非常重要!我会在后面的leetcode详解系列中慢慢讲解(我正在努力的填坑,手把手带着硬刷Leetcode,你们先去听公开课吧)。&/b&&br&&/p&&h2&Coursera: Princeton Algorithm&/h2&&p&&a href=&https://link.zhihu.com/?target=https%3A//zh.coursera.org/learn/algorithms-part1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&传送门&/a&。采用java语言,Princeton神级教授倾力讲授。&b&我比较推荐的是这门课的教材:&a href=&https://link.zhihu.com/?target=https%3A//www.amazon.cn/%25E7%25AE%%25B3%%25A1%259E%25E5%25A5%%25A8%%B-%25E9%259F%25A6%25E6%/dp/B01DN6FIRM/ref%3Dsr_1_1%3Fie%3DUTF8%26qid%3D%26sr%3D8-1%26keywords%3Dalgorithms& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&红书&/a&&/b&&b&。&/b&我买了一本,带去了美国。Josh Hug 的cs61b也参考了这本课本,因为Josh Hug是Princeton出去的大神。&br&&/p&&p&&b&首先,入门选手千万不要读算法导论!入门选手千万不要读算法导论!入门选手千万不要读算法导论!有多少人因为算法导论,从此对算法望而生畏。&/b&书当然是超级好的书,但是这本书更适合研究算法的人!而且如果没有人给你画重点,你几乎可以深陷其中,不能自拔。&/p&&p&与大部分的算法课不同是,这么课并没有过多注重于数学,而是一直在教你如何正确的implement一个算法,这也是我喜欢这门课的原因。其实这门课实现的算法都属于比较复杂的算法,对大部分人来说,如果能够轻松处理这些算法,那么其实工作和刷题中很少会遇到比这些更复杂的算法。老师的视频里面有各种动画,可以很好的帮你理解各种算法。这么课分&a href=&https://link.zhihu.com/?target=https%3A//zh.coursera.org/learn/algorithms-part1& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&part I &/a&和part II。Part I里面的所有内容都是非常重要的。Par II我只看了Graph和String。&/p&&p&红书最强之处在于,它的编程风格非常简洁明了,对我的&b&代码风格&/b&影响很大。书中对于每个算法的实现(merge sort, quick sort, graph algorithm)都是我见过的最好的。我曾经在面试的时候被人要求手写PriorityQueue,然后我写出了红书中的那种简洁的代码。我之后的代码几乎都在模仿这本书。其实代码的风格很重要,对于一个新手来说,越早的养成自己的风格,就意味着越早能写出bug free的代码。我在后期的文章里面会好好的总结这个问题,这里先把坑挖上。&/p&&br&&h2&CMU 15213 CSAPP&/h2&&p&我认为这是CMU Top 1 的神课。网上比较全的版本是UW的一个公开课的版本,UW的版本比CMU的版本简单了一点,但是也够用了。这门课原本是在Cousera上提供的,可惜Coursera改版之后被删了。现在可以在UW的&a href=&https://link.zhihu.com/?target=https%3A//courses.cs.washington.edu/courses/cse351/16sp/videos.html& class=& wrap external& target=&_blank& rel=&nofollow noreferrer&&官网&/a&上看到。这么课神就神在,它基本上把CS界的那些经典领域都不深不浅的introduce了一遍,所以这么课是cmu很多高阶课的prerequisite。而且这么课的作业非常的神,每个作业都设计的非常有趣,篇幅有限,不摊开讲了。这么课的教材(CSAPP)也是CS界的经典著作之一,有空一定要读读。这门课选用的语言是C语言。&/p&&br&&p&当时UW讲这门课的Prof Gaetano Borriello 已经在2015年去世了,可是他的课程依然影响着千千万万的人。&/p&&h2&后记&/h2&&p&篇幅好长,但好多内容都没有细说。还是留着大家自己去发现吧。&/p&&p&现在已经是2017了,MOOC的数量比当时大大增加了。可能有很多很好的课我并没有接触到,欢迎大家留言补充。以上只是介绍了CS的一些基础课,其实我也接触过一些高阶的课程,等有机会再介绍了。大家没事多去coursera和udacity上逛逛,活用google search,会找到很多有用的课程。&br&&/p&&br&&p&如果真的能够坚持上完这几门课,那么恭喜你,你的CS基础已经非常扎实了。可以成为一名光荣的码农了。回头想想,美国四大名校的神课,你上了三个:CMU+Princeton+Berkeley。&/p&&p&贵在坚持。如果没有十足的信念,或者充分的兴趣,其实一般人很难坚持的。所以下一篇文章准备给大家灌一篇鸡汤!&/p&&p&欢迎转载,请注明出处。辛辛苦苦写了一晚上,可是我还是0粉的状态。&/p&&br&&p&日 于 加州 三肉丝&/p&&p&--------------------------------------------------------------------------------------------------------&/p&&p&&b&Update(Jan 9, 2017):&/b&&/p&&p&很多朋友私信我了,实在有点多,回复不上还请多多见谅。下面是几个简单的Updates:&/p&&ul&&li&我本人并没有国内的就业经验,所以国内的就业情况我基本不知道,我比较熟悉的是北美留学和就业。&/li&&li&上面介绍的课程都是英文语音。&b&Udacity的Introduction to Computer Science 和Princeton的Algorithm都是有中英文字幕&/b&的。但是我建议你们观看英文字幕,英文是码农迟早要跨过的坎。CS的词汇不是很多,也不是很复杂,多看几遍应该都可以记住,听懂。Berkeley的课程视频是发布在Youtube上的,需要翻一翻,并没有原生字幕。但是Youtube自带自动Google生成的英文字幕(和翻译),虽然不敢说完全正确,但是可以参考一下。&/li&&li&以上的课程是我比较欣赏的课程,而且我都上过,当然其他还有很多优秀的课程(比如&b&Havard的CS50&/b&)。但是基于我自己没有上过,所以不太好做太多测评,感兴趣的同学可以自己发掘。这篇文章只是想告诉大家:&b&其实你想学的网上都有,能不能坚持下来就靠跟人修为了。&/b&&/li&&/ul&
(欢迎移步文章末尾看文章更新)自从2014年第一次接触到MOOC(网络公开课,对,就是可以免费上的那种)之后,我的人生轨迹彻底改变了。2014年,我面试腾讯实习被拒(主要我屁都不会),2015年底,我拿到了(Facebook,Google, LinkedIn) 的offer。读master的…
先说结论,VBA依旧是办公利器。以我的个人经历而言,在BCG做过三年咨询顾问,写了上万行的VBA程序,每个项目一千至几千行程序不等。最后将Excel用成了中控界面,类似EMACS,在Excel可以随意操控全公司的打印机、Word、Powerpoint等等,自动完成各种任务以及数据更新和抓取。依靠VBA,在效率上是一般同事的数倍甚至是高一个量级,你说VBA还是不是办公利器?&br&&br&不过题主得到的反馈也正常,许多高级程序员确实瞧不上VBA。因为程序员是有鄙视链的:汇编 &C &C++ &Python &Java及C#及PHP(这三者相互撕) &VB &HTML。在这长长的鄙视链中,甚至都没有VBA的位置。&br&&br&但是Office+VBA是图灵完备的,所以被程序员用来耍酷的各类性感语言能实现的大部分功能,VBA都能实现,而且往往是以更高效更快捷的方式,在这里不谈效率和优雅。较之Python等常用语言,VBA各有攻防各有优缺点。Python的优势当然是扩展性强、超越Office环境之后的适用性强、资源丰富以及效率高,而VBA的优点如下:&br&&ul&&li&环境不依赖,只需要打开装机自带的Office,然后按下Alt+F11就自动进入编程和执行环境&/li&&li&上手简单,学习曲线很平缓,甚至可以更简单的通过录制宏来解决写程序的问题,只需要在简单的代码基础上修修补补就可以执行,参考&a href=&https://www.zhihu.com/question//answer/& class=&internal&&Excel VBA 如何快速学习? - 何明科的回答&/a&&br&&/li&&li&与办公环境完美兼容,在Excel/Word/Powerpoint/Outlook/Access之间随便穿梭,比胶水语言还要简单易用&/li&&li&分享性和移植性很强,几乎所有测试通过的程序放到别的机器上也可轻易执行(如果不考虑各种本地文件位置)&/li&&/ul&&br&基于以上的优劣势对比,VBA仍然是当之无愧的办公利器之王。而且大家不用太在乎手中的工具(VBA还是Python或者其他),核心还是使用工具的人以及人的思考。&br&&br&下面列举Office+VBA实现的若干功能,真正为职场人士省时省事省力。大部分内容在回答(&a href=&https://www.zhihu.com/question//answer/& class=&internal&&Excel 到底有多厉害? - 何明科的回答&/a&)中已经出现过。不愿意点击过去阅读的,直接看下面的克隆内容。&br&&br&&b&1、批量修改格式&/b&&br&下图是利用Powerpoint中录制的宏再加上稍微修改的代码(甚至都称不上是改代码,大部分是改参数),将Powerpoint中所有的字体及字号进行统一修改。常做PPT而且需要根据老板的喜好改来改去的同学们,知道这个批处理功能有多么救命。&br&&figure&&img src=&https://pic3.zhimg.com/573d74cb3d835acefab6e_b.png& class=&content_image&&&/figure&&br&&br&&b&2、批量完成打印&/b&&br&刚进职场的新人,只要爸爸不是李刚,基本都做过影帝影后(影=印,各种复印打印的体力劳动)。特别是咨询投行服务行业,在大忽悠会议之前之后,花数小时或者整晚来打印数个文件,并不是天方夜谭。而且这件事情是对着同样一堆不断修改的文件,会经常不断重复发生。&br&&br&我写的第一个VBA程序就是完成对100多张Excel表格的自动打印,因为是第一个VBA程序,所以比较挫,基本上是宏录制之后来改的,没有使用参考书及搜索引擎,全靠F1和自动提示,所以贴出来特别纪念一下。但也让大家清楚VBA上手也多么容易。实现的功能就是将每周都要做一次的100多张表格的按顺序打印让机器自动做一遍,而且需要防卡纸:按下一个“妞”,就慢慢美妙结果的发生。&br&&figure&&img src=&https://pic2.zhimg.com/e7cd68bf4a6f60b935a05f5_b.png& data-rawwidth=&676& data-rawheight=&424& class=&origin_image zh-lightbox-thumb& width=&676& data-original=&https://pic2.zhimg.com/e7cd68bf4a6f60b935a05f5_r.png&&&/figure&后来这个程序的升级版是:调度多台打印机,进一步提高效率,以及将打印机卡纸造成队列错误的概率降到极小的范围内。&br&&br&&b&3、制作炫目视觉效果(图表、动画及油画)&/b&&br&图表制作是每个Office一族的必备任务,制得一手好表格,绝对是升职加薪和偷懒放风的利器。在回答(&a href=&https://www.zhihu.com/question//answer/& class=&internal&&黄焖鸡米饭是怎么火起来的? - 何明科的回答&/a&),就利用Excel+VBA做出数张炫酷的信息地图,利用VBA为每个省的图形涂色。&br&&figure&&img src=&https://pic2.zhimg.com/71d4c477d5dcc8ced48cdd_b.png& data-rawwidth=&1373& data-rawheight=&584& class=&origin_image zh-lightbox-thumb& width=&1373& data-original=&https://pic2.zhimg.com/71d4c477d5dcc8ced48cdd_r.png&&&/figure&(涂色部分来自于网上的一段程序,制作GIF动画的是自己完成的)&br&&br&同时,为了进一步增强炫酷结果,还利用VBA将这些连续变化的图表做成了GIF动画。&br&&figure&&img src=&https://pic4.zhimg.com/8a517ecb76ee9144e6beb_b.png& data-rawwidth=&1197& data-rawheight=&589& class=&origin_image zh-lightbox-thumb& width=&1197& data-original=&https://pic4.zhimg.com/8a517ecb76ee9144e6beb_r.png&&&/figure&&br&另外还可以利用Excel,把心仪妹子的图片拿到手,然后用Excel化成点阵图并进行油画效果的处理,然后送给她撩一撩。&br&&figure&&img src=&https://pic3.zhimg.com/ae03578effcf9a205d0ad3c267d9eaa6_b.png& class=&content_image&&&/figure&&br&&b&4、&/b&&b&撰写&/b&&b&八股文&/b&&br&这是帮朋友实现的一个项目,他们实验室是研究某类事故并对重大事故进行鉴定,最后发布word版的正式报告。之前的工作流程是在专业的软件中完成计算和仿真,最后按照正式报告八股文的行文,把各种关键信息填进去,最后写成Word文件。写报告的过程枯燥而没有技术含量,但却要反复进行。&br&&br&通过下图的Word+VBA,完成主要的交互界面并连接计算软件。在通过简单的交互获取主要信息后,在后台完成计算并将主要信息填写入八股文的Word模版,最终完成报告,同时将结构化的信息存入Access数据库。&br&&figure&&img src=&https://pic4.zhimg.com/7ad306a95db0a7197aa7_b.png& data-rawwidth=&866& data-rawheight=&521& class=&origin_image zh-lightbox-thumb& width=&866& data-original=&https://pic4.zhimg.com/7ad306a95db0a7197aa7_r.png&&&/figure&&br&&b&5、管理项目及同步内容&/b&&br&这是协助某国际大型汽车制造厂完成新品牌及其新款车型上市,面临车型即将断档的窘境,该新车型的上市非常关键,不能错失时间节点。然而,新车型上市涉及到无数分支:制造、产品、市场、渠道、营销、公关、财务等等,同时还要协调欧洲的两个总部以及中国的两个分部。&br&&br&这次咨询的核心任务就是项目管理,总控整个大项目的进度,并每周向中国区的CEO汇报进度并发掘出易出现问题的关键节点以调配资源。我们4个咨询顾问分配下去各自负责几个部门或者项目分支,和团队一起规划流程、画甘特图、确认里程碑及时间点、安排负责人等等。当每天回到办公室大家将进度汇总在一起的时候发现了挑战及难点,每条任务线并不是独立发展的,而是各条任务线交织在一起并互相影响。&br&&ul&&li&某些核心人员在多个任务线出现。比如:负责预算的财务人员,几乎要出现在各条线中负责相关预算的审批环节&/li&&li&某些任务线的里程碑是其他任务线里程碑的必要条件而相互关联。比如:新车的下线时间影响发布会的时间,相关法规测试的通过又影响车辆的下线时间等等&/li&&/ul&&br&当任务线增多以及任务线之间的交叉越发频繁的时候,汇总的任务将会几何级数增加,这就是我们在项目过程中遇到的问题。于是我利用Excel+VBA完成了这个工作的自动化。主要实现的功能:&br&&ul&&li&自动将4个顾问手中分散的Excel文件汇集在一起形成一个大的总表,如下图&/li&&li&各顾问手中的表格是按照部门维度来划分的,汇总后需要按照不同的维度来输出不同类型的表格,比如:按任务线输出表格、按责

我要回帖

更多关于 stewam 的文章

 

随机推荐