-
Notifications
You must be signed in to change notification settings - Fork 0
/
search.xml
640 lines (640 loc) · 511 KB
/
search.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title><![CDATA[Web API 接口参考]]></title>
<url>%2F2020%2F12%2F16%2Fweb-api%2F</url>
<content type="text"><![CDATA[DOM  文档对象模型 (DOM) 将 web 页面与到脚本或编程语言连接起来。DOM 模型用一个逻辑树来表示一个文档,树的每个分支的终点都是一个节点(node),每个节点都包含着对象(objects)。DOM 的方法(methods)让你可以用特定方式操作这个树,用这些方法你可以改变文档的结构、样式或者内容。节点可以关联上事件处理器,一旦某一事件被触发了,那些事件处理器就会被执行。 Document  Document 接口表示浏览器中载入的 DOM 树,向网页文档本身提供了全局操作功能。 构造器:new Document()常用属性 Document.URL:以字符串形式返回文档的地址栏链接 Document.title:获取或设置当前文档的标题 Document.body:返回当前文档的 <body> 或 <frameset> 节点 Document.documentElement:返回当前文档的直接子节点 Document.head:返回当前文档的 <head> 元素 Document.images:返回当前文档中所包含的图片的列表 Document.documentURI:以字符串的类型,返回当前文档的路径 Document.links:返回一个包含文档中所有超链接的列表 Document.scripts:返回文档中所有的 <script> 元素 常用方法 Document.createElement():创建一个新的元素 Document.createEvent():创建一个 event 对象 Document.createTextNode():创建一个文本节点 document.getElementById(String id):返回一个匹配特定 ID 的元素 Document.getElementsByName():根据给定的 name 返回一个在 (X)HTML document 的节点列表集合 Document.getElementsByClassName():返回一个包含了所有指定类名的子元素的类数组对象 Document.getElementsByTagName():返回一个包括所有给定标签名称的元素的 HTML 集合 HTMLCollection Document.querySelector():返回文档中与指定选择器或选择器组匹配的第一个 HTMLElement 对象。 如果找不到匹配项,则返回 null Document.querySelectorAll():返回与指定的选择器组匹配的文档中的元素列表 (使用深度优先的先序遍历文档的节点)。返回的对象是 NodeList Document.open():打开一个要写入的文档 Document.write():将一个文本字符串写入一个由 document.open() 打开的文档流 Document.close():用于结束由 对文档的 Document.write() 写入操作,这种写入操作一般由 Document.open() 打开 Document.whiteln():向文档中写入一串文本,并紧跟着一个换行符 参考地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Document Element  Element 是一个通用性非常强的基类,所有 Document 对象下的对象都继承自它。这个接口描述了所有相同种类的元素所普遍具有的方法和属性。 使用document.getElementById,document.getElementsByName,document.getElementsByClassName,document.getElementsByTagName 获取到 element 常用属性 Element.attributes:返回一个与该元素相关的所有属性集合 Element.classList:返回该元素包含的 class 属性 Element.className:返回该元素的 class Element.id:返回该元素的 id Element.innerHTML:设置或获取 HTML 语法表示的元素的后代,设置 HTML 时可能会造成安全问题 Element.tagName:返回当前元素的标签名 常用方法 Element.getAttribute():返回元素上一个指定的属性值。如果指定的属性不存在,则返回 null 或 “” Element.getAttributeNames():返回一个 Array,该数组包含指定元素(Element)的所有属性名称,如果该元素不包含任何属性,则返回一个空数组。 Element.hasAttribute():返回一个布尔值,指示该元素是否包含有指定的属性(attribute)。 Element.setAttribute():设置指定元素上的某个属性值。如果属性已经存在,则更新该值;否则,使用指定的名称和值添加一个新的属性。 Element.removeAttribute():从指定的元素中删除一个属性。 Element.getElementsByClassName():返回一个即时更新的 HTMLCollection,包含了所有拥有指定 class 的子元素。 Element.getElementsByTagName():返回一个动态的包含所有指定标签名的元素的 HTML 集合 HTMLCollection。 Element.querySelector():返回与指定的选择器组匹配的元素的后代的第一个元素。 Element.querySelectorAll(selectors):selectors 是一组 CSS 选择器,返回一个 non-live 的 NodeList, 它包含所有元素的非活动节点,该元素来自与其匹配指定的 CSS 选择器组的元素。(基础元素本身不包括,即使它匹配。) Event  Event 接口表示在 DOM 中出现的事件,很多 DOM 元素可以被设计接收(或者监听) 这些事件, 并且执行代码去响应(或者处理)它们。通过 EventTarget.addEventListener()方法可以将事件处理函数绑定到不同的 HTML elements 上。这种绑定事件处理函数的方式基本替换了老版本中使用 HTML event handler attributes 来绑定事件处理函数的方式。除此之外,通过正确使用 removeEventListener()方法,这些事件处理函数也能被移除。 构造器:new Event(typeArg, eventInit)typeArg 表示所创建事件的名称,eventInit 为可选项,接受以下字段:“bubbles”,可选,Boolean 类型,默认值为 false,表示该事件是否冒泡。“cancelable”,可选,Boolean 类型,默认值为 false, 表示该事件能否被取消。“composed”,可选,Boolean 类型,默认值为 false,指示事件是否会在影子 DOM 根节点之外触发侦听器。 常用属性 Event.target:触发事件的对象 (某个 DOM 元素) 的引用 Event.currentTarget:当事件沿着 DOM 触发时事件的当前目标。 Event.type:表示该事件对象的事件类型 EventTargetEventTarget 是一个 DOM 接口,由可以接收事件、并且可以创建侦听器的对象实现。 构造器:new EventTarget(),创建一个新的 EventTarget 对象实例 常用方法 EventTarget.addEventListener():将指定的监听器注册到 EventTarget 上,当该对象触发指定的事件时,指定的回调函数就会被执行。 EventTarget.dispatchEvent():向一个指定的事件目标派发一个事件, 并以合适的顺序同步调用目标元素相关的事件处理函数。 EventTarget.removeEventListener():删除使用 EventTarget.addEventListener() 方法添加的事件。 URL  URL 接口用于解析,构造,规范化和编码 URLs,如果浏览器尚不支持 URL()构造函数,则可以使用 Window 中的 Window.URL 属性。 构造器:new URL()常用属性:host hostname href pathname port protocol search searchParams username常用方法 createObjectURL():创建一个 DOMString,其中包含一个表示参数中给出的对象的 URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的 URL 对象表示指定的 File 对象或 Blob 对象。 revokeObjectURL():销毁之前使用 URL.createObjectURL()方法创建的 URL 实例 toJSON():返回一个序列化的 URL toString():字符串化方法返回一个 URL 参考地址:https://developer.mozilla.org/zh-CN/docs/Web/API/URL WindowNodeFullScreenhttps://developer.mozilla.org/zh-CN/docs/Web/API/Fullscreen_API Storagehttps://developer.mozilla.org/zh-CN/docs/Web/API/Storage_APIhttps://developer.mozilla.org/zh-CN/docs/Web/API/Web_Storage_API Historyhttps://developer.mozilla.org/zh-CN/docs/Web/API/History_API WebSocketshttps://developer.mozilla.org/zh-CN/docs/Web/API/Websockets_API WebGLhttps://developer.mozilla.org/zh-CN/docs/Web/API/WebGL_API 参考资料:https://developer.mozilla.org/zh-CN/docs/Web/API]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Temer EDH combo]]></title>
<url>%2F2020%2F11%2F26%2FEDH-combo%2F</url>
<content type="text"><![CDATA[List the useful 2-4 cards combos in my EDH decks. Color now mostly used: RUG Commander now mostly used Kalamax, the Stormsire 风暴君父卡拉马科斯 | combo Xyris, the Writhing Storm 纠拧风暴灾里斯 | mid & token Haldan, Avid Arcanist 热切奥术师哈丹 / Pako, Arcane Retriever 奥术猎犬帕科 | enchantment combo Omnath, Locus of the Roil 狂搅核欧那斯 | landfall / element aggro Animar, Soul of Elements 元素之魂阿尼玛 | combo Commander now in testing: Brago, King Eternal 不朽国王布莱戈 Derevi, Empyrial Tactician 穹光策士德蕾薇 Golos, Tireless Pilgrim 不倦朝圣械戈罗斯 Sisay, Weatherlight Captain 晴空号船长西赛 Omnath, Locus of Creation 生机核欧那斯 Combos in KalamaxKalamax, the Stormsire + Reverberate/Twincast… => Infinite large Kalamax => Soul’s fire prerequisites:Kalamax tappedNo instants played this turnresponse the instant or sorcery from other playersEnough mana to cast spells Cast any copy instant Kalamax triggers (first Instant played this turn), copying instant Have the copy and target the original Kalamax triggers off of the copying, gaining a +1/+1 counter The copy resolves, creating another copy Repeat steps In your turn you get infinite large Kalamax Kalamax, the Stormsire + Chandra’s Ignition + Reverberate/Twincast => Infinite damage/large Kalamax prerequisites:Kalamax tappedNo instants played this turnEnough mana to cast spells Cast Chandra’s Ignition, holding priority Cast Reverberate targeting Chandra’s Ignition Kalamax triggers (first Instant played this turn), copying Reverberate Have the copy of Reverberate target the original Kalamax triggers off of the copying, gaining a +1/+1 counter The copy of Reverberate resolves, creating another copy Repeat steps 4-6 until Kalamax is adequately large, then copy Chandra’s Ignition with Reverberate, ending the loop and dealing an arbitrarily large amount of damage to your opponents (and each other creature) Kalamax, the Stormsire + Ral, Storm Conduit + Reverberate/Twincast… => Infinite damage/large Kalamax prerequisites:Kalamax tappedNo instants played this turnresponse the instant or sorcery from other playersEnough mana to cast spells Cast any copy instant, triggering Ral and Kalamax, copying instant Have the copy and target the original, triggering Ral Kalamax triggers off of the copying, gaining a +1/+1 counter The copy resolves, creating another copy, triggering Ral Repeat steps until Ral trigger infinite times, then copy the first ability other player played, ending the loop and dealing an arbitrarily large amount of damage to your opponents and get infinite large Kalamax Fury Storm + Ral, Storm Conduit => Infinite damage prerequisites:must have cast your commander at least once2RR mana available Cast your instant or sorcery, triggering Ral Resolve the Ral trigger and respond to the instant or sorcery by casting Fury Storm targeting the instant or sorcery which triggers Fury Storm and Ral Place the Ral trigger on top and the Fury Storm trigger below it and resolve the Ral trigger Resolve the Fury Storm trigger targeting the original Fury Storm with the copy which triggers Ral Resolve the Ral trigger and resolve the Fury Storm copy copying Fury Storm and triggering Ral Repeat step 5 https://CommanderSpellbook.com/?id=5022 Heart Defence/Chord of Calling => Kiki-Jiki, Mirror Breaker + Aphetto Alchemist/Corridor Monitor => Infinite combat damage + blue mana => Thassa’s Oracle prerequisites:Kiki-Jiki, Mirror Breaker and Aphetto Alchemist on the battlefieldThassa’s Oracle in hand and UU mana to cast it Activate Kiki-Jiki, targeting Aphetto Alchemist to create a hasty token copy of it Activate the token’s ability to untap Kiki-Jiki Repeat the loop to generate an arbitrarily large number of tapped Aphetto Alchemist tokens, each of which is worth blue mana devotion Cast Thassa’s Oracle As your devotion to blue mana is greater than the number of cards in your library, you win the game with its ETB trigger Primal Amulet + Frantic Search + Narset’s Reversal => Infinite colored mana/card draw/storm count => brain freeze prerequisites:primal amulet with 3 countersfrantic search and narset’s reversal in handaccess to 1UU mana from lands cast frantic search for 1U mana (reduced by primal amulet) let the trigger from primal amulet resolve to transform primal amulet in to primal wellspring you now have an extra land, use primal wellspring to tap for blue mana and an additional blue mana from an other land to pay for narset’s reversal, creating a copy of narset’s reversal let the copy of narset’s reversal target the original narset’s reversal to bounce it and create an other copy the second copy of narset’s reversal targets frantic search, returning it to your hand and creating a copy of frantic search to untap 3 lands (must untap primal wellspring) and loot 2 cards tap 3 lands for 2U mana and use the blue mana from primal wellspring + 2 mana from the other lands to cast frantic search let the copy of frantic search resolve to untap 3 lands and loot 2 tap 3 lands for 1U mana and use the blue manaa from primal wellspring blue mana from the other lands start the loop again at step 3 by casting narset’s reversal from primal wellspring, netting you 1 mana and 2 loots each loop https://commanderspellbook.com/?id=4843 Mizzix of the Izmagnus + Bonus Round + Frantic Search + Narset’s Reversal => Infinite mana/loot/storm count => brain freeze prerequisites:Bonus Round, Frantic Search and Narset’s Reversal in handMizzix on the battlefieldYou have at least 1 experience counterAbility to produce a (R/U)(R/U)(R/U) mana from lands Cast Bonus Round for RR Let the Mizzix trigger and bonus round resolve, you now have 2 experience counters Cast Frantic search for U (reduced by mizzix) Let the copy from bonus rounds resolve to loot 2 cards, untap 3 lands that can tap for at least UU Cast Narset’s Reversal for UU, let the copy from bonus rounds resolve, targeting the original Narset’s Reversal This bounces the original and makes a new copy which targets the original frantic search This bounces the original frantic search and creates a new copy Let the frantic search copy resolve to loot 2 cards and untap 3 lands You now have frantic search and narset’s reversal back in your hand and can start the loop again https://CommanderSpellbook.com/?id=4930 High Tide + Archaeomancer + Snap => Infinite storm count/colored mana => brain freeze prerequisites:All cards in hand5 untapped Islands under your control Tap 1 Island, producing U, to cast High TideTap 2 Islands, producing 4U, to cast Archaeomancer, getting back High TideTap 1 Island, producing 2U, to cast High Tide, floating UTap 1 Island, producing 3U to cast Snap to return Archaeomancer and untap two islands, floating 2UTap 2 Islands, procuing 6U, to cast Archaeomancer, returning Snap and floating 2URepeat steps 4-5 # link:Scryfall: card searchMTGTop8MTG Deck BuilderEDHReccommander SpellbookcEDH Decklist Database]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>MTG</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Vue功能实现和使用技巧]]></title>
<url>%2F2020%2F11%2F10%2Fvue-notes%2F</url>
<content type="text"><![CDATA[汇总记录前端开发时,使用 Vue 框架遇到的功能实现和开发技巧。 Vue 动态组件使用动态组件功能用于在不同组件之间进行动态切换,可以通过 Vue 的 <component> 元素加一个特殊的 is attribute 来实现 // `currentComponent` 改变时显示的组件同时改变<component :is="currentComponent"></component><button @click="(currentComponent === 'A') ? 'B':'A'">Switch</button><script>//引入组件A以及组件Bimport A from "./a"import B from "./b"export default { components: {A, B}, data () { return { //默认显示组件A,若字符串为B则显示组件B,name为component声明 currentComponent: 'A' } }}</script> v-show,v-if,:is 之间的区别 v-show 会同时加载两个组件,两个组件的生命周期都会触发,会造成不必要的性能浪费,而且切换的时候不会再创造挂载一次,无法重新渲染。v-if 不会造成同时加载两个组件,但 v-if 每次切换都会创造挂载一次,如果没有重新渲染的需要,会造成性能浪费。:is 可以通过 keep-alive 标签缓存,被该标签包裹的组件会被缓存下来,每次点击都不会重新渲染,避免了重渲染导致的性能问题。include 和 exclude 属性也允许组件有条件地缓存。二者都可以用逗号分隔字符串、正则表达式或一个数组来表示。 <!-- 逗号分隔字符串 --><keep-alive include="a,b"> <component :is="currentComponent"></component></keep-alive><!-- 正则表达式 (使用 v-bind) --><keep-alive :include="/a|b/"> <component :is="currentComponent"></component></keep-alive><!-- Array (use v-bind) --><keep-alive :include="['a', 'b']"> <component :is="currentComponent"></component></keep-alive> 动态路由匹配动态路由用于把某种模式匹配到的所有路由,全都映射到同个组件,可以在 vue-router 的路由路径中使用“动态路径参数”(dynamic segment) 来达到这个效果。一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。 const router = new VueRouter({ routes: [ // 动态路径参数 以冒号开头 { path: '/user/:id', component: User }, ],}) 页面跳转和导航 定义链接实现声明式导航 <router-link :to="..."> 内部调用 router.push 方法实现页面导航 <router-link :to="{name: 'detail', params: {name: 1}}"> xxx </router-link><router-link :to="{name: 'detail', query: {id: 1}}"> xxx </router-link> 可以使用 this.$route.params 或 this.$route.params 获取路由参数。 router 实例实现编程式导航 在 Vue 实例内部,可以通过 $router 访问路由实例,可以调用 this.$router.push 方法,向 history 栈添加一个新的记录,点击浏览器后退按钮时也可以回到之前的 URL。params 相对应的是 name, query 相对应的是 path // 字符串router.push('home')// 对象router.push({ path: 'home' })// 命名的路由/user/123router.push({ name: 'user', params: { uid: '123' } }) // 刷新后参数会被清空router.push({ path: `/user/${userId}` }) // 刷新后参数不会被清空// 带查询参数,/home?uid=123router.push({ path: 'home', query: { uid: '123' } }) // 刷新后不会被清空 router.replace('') 跳转页面会替换掉原有的 history 记录 router.go(n) 在 history 记录中前进或后退多少步 keep-alive 网页性能优化keep-alive 主要用于保留组件状态或避免重新渲染 DOM 导致性能降低,通常都会在 app.vue 的 <router-view/> 外面加一层 <keep-alive> <keep-alive> <router-view /></keep-alive> 这样做也会导致一些问题,当组件的值更新后组件没有被重新渲染,做到动态显示需要使用额外生命周期函数 activated进入页面会执行 mounted 和 activated,当修改值后再次进入首页不会再执行 mounted 触发新的数据请求,但是 activated 会继续执行。可以在 activated 函数中判断新数据和前一次显示是否相同,如果不同再次触发 ajax 数据请求。 mounted () { this.lastData = this.data; this.getNewData();}activated () { if (this.lastData !== this.data) { this.lastData = this.data; this.getNewData(); }} 在路由更新后页面由于 keep-alive 的缓存不会执行 mounted 触发刷新,需要设置路由的 key 值,在每次进入页面时比较路由名称,若不相同则刷新页面。 /*App.vue*/<keep-alive> <router-view :key="key" /></keep-alive><script>export default { name: 'App', computed: { key () { return this.$route.name !== undefined ? this.$route.name + +new Date() : this.$route + +new Date() } }}</script> Vuex 数据防刷新丢失引入 vuex-persist 插件将状态保存至 cookie 或者 localStorage 中,刷新后数据不丢失。 import VuexPersistence from 'vuex-persist'const vuexLocal = new VuexPersistence({ storage: window.localStorage,})const store = new Vuex.Store({ state: { ... }, mutations: { ... }, actions: { ... }, plugins: [vuexLocal.plugin]}) 自定义指令避免误触和多次点击使用 Vue.directive 自定义防误触指令 import Vue from 'vue'const preventReClick = Vue.directive('preventReClick', { inserted: function (el, binding) { // 增加监听事件 el.addEventListener('click', () => { if (!el.disabled) { el.disabled = true setTimeout(() => { el.disabled = false }, binding.value || 3000) } }) },})export default { preventReClick } 制作可复用组件复用组件需要在样式和功能上做到继承和迭代,是在系统整体设计时抽象出的组件,多为布局组件,不涉及详细的功能实现。组件需要做到高内聚低耦合,组件内独立交互,功能受控于组件本身。 // 按钮组件抽象,样式设置为外部继承 cname,和内部自定义 button,留出按钮名称 title 和 <slot> 插槽作为具体内容的补充空间<div :class="[button, cname]"> <div>{{ title }}</div> <slot /></div><script>export default { name: 'BigBtn', // 通过 props 传入外部参数 props: { cname: { type: String, default: '' }, title: { type: String, default: 'title' } }, // 设置内部定义的样式 data () { return { button: 'button' } }}</script><style lang="stylus">// 引入样式@import "~@/styles/button.styl".button bigBtn() // 默认样式.blueBtn bigBtn($btnColor: $btnBlue) // cname 传入 blueBtn 设置颜色为蓝色.greenBtn bigBtn($btnColor: $btnGreen) // cname 传入 greenBtn 设置颜色为绿色</style> 上传文件功能使用 element-ui 的 upload 功能实现图片展示,上传和读取,on-change 触发文件状态改变时的钩子,调用上传照片 api 将照片数据传递到后台;on-preview 用于显示已上传的图片的缩略图;传递多个文件时文件列表存储在 file-list 中。 <el-upload action="actionUrl" list-type="picture-card" ref="upload" :file-list="fileList" :auto-upload="false" :on-change="getFile" :on-preview="handlePictureCardPreview"> <div slot="tip" class="el-upload__tip">上传一张jpg/png文件</div> <el-icon class="el-icon-plus"></el-icon></el-upload> // 获取文件信息getFile (file) { let uid = this.$store.state.currentUid // 调用上传照片的api api._updImage(uid, this.aid, res).then(res => { ... })} 若上传 base64 位图片需要进行转码之后调用 api 上传: // 图片转base64getBase64 (file) { return new Promise((resolve, reject) => { let reader = new FileReader() let imgResult = '' reader.readAsDataURL(file) reader.onload = function () { imgResult = reader.result } reader.onerror = function (error) { reject(error) } reader.onloadend = function () { resolve(imgResult) } })} Vuex 监听状态变更Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。 state: { updFlag: false},// 添加计算属性,依赖值改变时重新计算getters: { updFlag: state => state.updFlag},// 执行状态变更mutations: { updateFlag (state, update) { state.updFlag = update },} 兄弟组件,跨多层组件之间事件传递方法官方链接:集中式的事件中间件 使用集中的事件处理器,建立一个空的 vue 实例实现了事件分发接口。在初始化 web app 的时候,给 data 添加一个 eventhub 的空 vue 对象。然后在组件中,可以使用 $emit,$on,$off 分别来分发、监听、取消监听事件。 new Vue({ el: '#app', router, render: (h) => h(App), data: { eventHub: new Vue(), },}) 或者在初始化 Vue 对象之前给原生对象增加 eventHub 属性,这样在组件内部 就可以直接调用$eventHub对象。Vue.prototype.$eventHub= Vue.prototype.$eventHub || new Vue() 发送数据:this.$root.eventHub.$emit('YOUR_EVENT_NAME', yourData)接收数据:this.$root.eventHub.$on('YOUR_EVENT_NAME', yourData)销毁数据:this.$root.eventHub.$off() // 在组件销毁时需要结束绑定,使用 $off 方法 // 发送数据methods: { addTodo: function () { eventHub.$emit('add-todo', { text: this.newTodoText }) this.newTodoText = '' }, deleteTodo: function (id) { eventHub.$emit('delete-todo', id) }} // 接收数据methods: { addTodo (newTodo) { this.todos.push(newTodo) }, deleteTodo (todoId) { this.todos = this.todos.filter(function (todo) { return todo.id !== todoId }) }}created () { eventHub.$on('add-todo', this.addTodo) eventHub.$on('delete-todo', this.deleteTodo)},// 最好在组件销毁前清除事件监听beforeDestroy () { eventHub.$off('add-todo', this.addTodo) eventHub.$off('delete-todo', this.deleteTodo)} 回到顶部功能使用 element-ui 中提供的功能实现: <el-backtop target=".page-component__scroll .el-scrollbar__wrap" visibility-height="200" right="30" bottom="30"> up</el-backtop> 也可以使用 better-scroll 插件实现,通过监听下拉时 y 轴的移动距离显示上拉按钮,点击后触发返回顶部事件。 // 回到开头toTop () { if (this.toTop) { // 延迟20ms后在1s内回到顶部 setTimeout(() => { this.scrollTo(0, 0, 1000) }, 20) }} element-ui 按需引入通过借助 babel-plugin-component 或直接修改 .babelrc 文件,我们可以只引入需要的组件,以达到减小项目体积的目的。 引入插件:npm install babel-plugin-component -D修改 babel 配置文件: "plugins": [ [ "component", { "libraryName": "element-ui", "styleLibraryName": "theme-chalk" } ] ] 在 src 文件夹中 plugins 文件夹内新建一个 element.js 文件,导入需要的组件 // 导入自己需要的组件import Vue from 'vue'import 'element-ui/lib/theme-chalk/index.css'import { Select, Option, OptionGroup, Input, Tree, Dialog, Row, Col,} from 'element-ui'const element = { install: function (Vue) { Vue.use(Select) Vue.use(Option) Vue.use(OptionGroup) Vue.use(Input) Vue.use(Tree) Vue.use(Dialog) Vue.use(Row) Vue.use(Col) },}export default element 最后在 main.js 中引入 element.js 文件 import './plugins/element.js' 表单设置日期限制element-ui 支持在创建表单时使用规则校验,可以在校验中自定义校验规则。 在日期选择时需要实现截止日期必须大于等于开始日期,在 vue 组件中定义表单数据和校验规则并在 endDate 中自定义校验规则 checkEnd: data () { return: { ruleForm: { startDate: '', endDate: '' } rules: { startDate: [ { required: true, message: '请选择开始日期', trigger: 'change' } ], endDate: [ { required: true, message: '请选择截止日期', trigger: 'change' }, { validator: checkEnd, trigger: 'change' } ] } },} 在 data 中设置变量 checkEnd 来实现校验规则,校验错误时返回提示: data () { let checkEnd = (rule, value, callback) => { let startDate = this.ruleForm.startDate if (startDate === '') { callback(new Error('请先选择开始日期!')) } let start = new Date(startDate) let end = new Date(value) if ((start !== '') && (end < start)) { callback(new Error('结束日期不能小于开始日期!')) } else { callback() } }} 表单身份证校验通过自定义表单校验规则进行身份证的校验,新建 idValidate.js 文件实现身份证校验算法。 let checkId = (rule, value, callback) => { let errorMsg = idValidate(value) if (errorMsg !== '') { callback(new Error(errorMsg)) } else { callback() }} /* idValidate.js */// 身份校验的方法export default function isIdentityId(identityId) { const pattern = /(^\d{15}$)|(^\d{17}(\d|X|x)$)/ // 15或18位长度或格式校验 // 地区校验 const aCity = { 11: '北京', 12: '天津', 13: '河北', 14: '山西', 15: '内蒙古', 21: '辽宁', 22: '吉林', 23: '黑龙江', 31: '上海', 32: '江苏', 33: '浙江', 34: '安徽', 35: '福建', 36: '江西', 37: '山东', 41: '河南', 42: '湖北', 43: '湖南', 44: '广东', 45: '广西', 46: '海南', 50: '重庆', 51: '四川', 52: '贵州', 53: '云南', 54: '西藏', 61: '陕西', 62: '甘肃', 63: '青海', 64: '宁夏', 65: '新疆', 71: '台湾', 81: '香港', 82: '澳门', 91: '国外', } // 出生日期验证 const sBirthday = ( identityId.substr(6, 4) + '-' + Number(identityId.substr(10, 2)) + '-' + Number(identityId.substr(12, 2)) ).replace(/-/g, '/') let d = new Date(sBirthday) // 身份证号码校验 最后4位 包括最后一位的数字/字母X let sum = 0 let weights = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2] let codes = '10X98765432' let errorMsg = '' for (let i = 0; i < identityId.length - 1; i++) { sum += identityId[i] * weights[i] } const last = codes[sum % 11] // 计算出来的最后一位身份证号码 if (identityId === '') { errorMsg = '身份证号不能为空' } else if (!pattern.exec(identityId)) { errorMsg = '身份证长度或格式错误' } else if (!aCity[parseInt(identityId.substr(0, 2))]) { errorMsg = '身份证地区非法' } else if ( sBirthday !== d.getFullYear() + '/' + (d.getMonth() + 1) + '/' + d.getDate() ) { errorMsg = '出生日期非法' } else if (identityId[identityId.length - 1] !== last) { errorMsg = '输入的身份证号校验码不正确' } return errorMsg} 持续拉取后台数据实现后台请求数据时不一次性返回,需要返回一部分就显示一部分。setInterval() 方法可按照指定的周期(以毫秒计)来调用函数或计算表达式。 methods: { func () { ... }}mounted () { // 建议使用箭头函数 setInterval(() => { this.func() }, 500)} 添加和删除属性(不再使用)在 vue 中,直接使用赋值语句无法触发视图页面更新;对于已经创建的实例,Vue 不允许动态添加根级别的响应式 property。但是,可以使用 set 和 delete 修改 property 来触发视图更新。 Vue.set( target, propertyName/index, value ) 参数:{Object | Array} target{string | number} propertyName/index{any} value 还可以使用 vm.$set 实例方法,是全局 Vue.set 方法的别名 Vue.delete( target, propertyName/index ) 参数:{Object | Array} target{string | number} propertyName/index 还可以使用 vm.$delete 实例方法 vue 2.x 之后,Vue.set 和 Vue.delete 在实例上将不再起作用。现在都强制在实例的 data 选项中声明所有顶级响应值,通过改变 data 值实现相应。 其它注意事项 监听组件原生事件@click.native=可以在子组件监听根元素的原生事件,不需要通过$emit事件 ref 属性给 DOM 元素或子组件注册引用信息,引用信息将会注册在父组件的 $refs 对象上,如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例。通过this.$refs.ref访问 dom 节点或组件实例(data) render: h => h(App)h 作为 createElement 的别名是 Vue 生态系统中的一个通用惯例。它来自单词 hyperscript,这个单词通常用在 virtual-dom 的实现中。hyperscript 本身指生成 HTML 结构的 script 脚本。 — Even You render: function (createElement) { return createElement(App);}// h <- createElementrender: function (h) { return h(App);}// ES6render: h => h(App) webpack 打包后引用路径问题config\index.js 中的 build 模块修改导出路径 assetsPublicPath 为 ./,使 index.html 和 static 文件夹在同一级目录下面。 module.exports = { build: { ... assetsPublicPath: './', }} es6 语法兼容问题build\webpack.base.conf.js 中的 entry 模块加入 babel-polyfill,让程序在打包时同时兼容低版本的浏览器。vue3 版本中在自建的 vue.config.js 中添加 webpack config,将 entry 定义为 @babel/polyfill module.exports = {context: path.resolve(__dirname, '../'),entry: { app: ['babel-polyfill', './src/main.js']},// entry: {// app: './src/main.js',// "babel-polyfill": "babel-polyfill" configureWebpack: (config) => { if (process.env.NODE_ENV === 'production') { return { // 解决浏览器兼容ES6 entry: { main: ['@babel/polyfill'], } ... } }} json 转换(重要)vuex 里将状态保存到缓存中,会用到 json 转换,我们保存的状态都是数组,而 localStorage 只支持字符串将数组传递到后台时也需要使用 JSON.stringify() 转换为字符串格式,回传时再转换为数组 JSON.stringify(state.dataList) // array -> stringJSON.parse(window.localStorage.getItem('dataList')) // string -> array v-for 参数顺序变更vue2.x 中,当包含 index 时,之前遍历数组时的参数顺序是 (index, value)。现在是 (value, index),来和 JavaScript 的原生数组方法 (例如 forEach 和 map) 保持一致。当包含 property 名称/key 时,之前遍历对象的参数顺序是 (name, value)。现在是 (value, name),来和常见的对象迭代器 (例如 lodash) 保持一致。 箭头函数箭头函数的 this 在函数创建期间(普通函数在执行时绑定)完成绑定,this 指向该箭头函数被声明时所在的作用域对象。箭头函数不能作为构造函数,没有 arguments,不能作为生成器函数。 数组去重Set 是无序的类数组数据类型,有相同的 key 和 value,无重复数值,可以创建 Set 实例进行数组去重newArr = [...new Set(arr)] 参考资料:https://router.vuejs.org/zh/guide/essentials/navigation.htmlhttps://vuex.vuejs.org/zh/https://better-scroll.github.io/docs/zh-CN/https://element.faas.ele.me/#/zh-CN/https://cn.vuejs.org/v2/guide/migration.htmlhttps://github.com/axios/axioshttps://juejin.cn/post/6844903613609803783]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Webpack程序打包学习笔记(3) —— Babel]]></title>
<url>%2F2020%2F07%2F13%2FWebpack_3%2F</url>
<content type="text"><![CDATA[Babel 是一个 JavaScript 的静态分析编译器,在不需要执行代码的前提下对代码进行分析和处理。要实现 Babel 从一个语法转换成另外一个语法,需要经过三个主要步骤:解析(Parse),转换(Transform),生成(Generate)。 Webpack 程序打包学习笔记(1)Webpack 程序打包学习笔记(2) Babel 分析步骤解析:指的是首先将代码经过词法解析和语法解析,最终生成一颗 AST(抽象语法树),在 Babel 中,语法解析器是 Babylon(@babel/parser)转换:得到 AST 之后,可以对其进行遍历,在此过程中对节点进行添加、更新及移除等操作,Babel 中 AST 遍历工具是@babel/traverse生成:经过一系列转换之后得到的一颗新树,要将树转换成代码,就是生成的过程,Babel 用到的是@babel/generator 使用@babel/parse 来生成 AST // index.jsconst fs = require('fs')const babel = require('@babel/core')const traverse = require('@babel/traverse').defaultconst gen = require('@babel/generator').default// 读取 source.js内容let source = fs.readFileSync('./source.js')// 使用 babel.parse方法babel.parse(source, (err, ast) => { // ast就是树 console.log(ast)}) 使用@babel/traverse,进行遍历,会得到一个类似 Html 结构的树形结构 ...babel.parse(source, (err, ast) => { // console.log(ast) let indent = '' traverse(ast, { // 进入节点 enter(path) { console.log(indent + '<' + path.node.type + '>') indent += ' ' }, // 退出节点 exit(path) { indent = indent.slice(0, -2) console.log(indent + '<' + '/' + path.node.type + '>') }, })}) 使用@babel/generator 进行生成 ...babel.parse(source, (err, ast) => { // console.log(ast) let indent = '' traverse(ast, { ... }) // 生成新的 ast,然后使用generator生成 code console.log(gen(ast).code);}) Babel 做 ES6 语法转换命令行Babel 是 JavaScript 的一个编译器,能够将 ES6+ 语法转换为 ES5 语法。Babel 本身自己带有 CLI(Command-Line Interface,命令行界面) 工具,可以单独安装使用:npm i -D @babel/core @babel/cli安装@babel/preset-env 进行语法转换,执行 CLI 的时候添加 —presets: # 安装开发依赖npm i webpack babel-loader webpack-cli @babel/core @babel/preset-env @babel/plugin-transform-runtime -D# 执行 CLI 添加--presetsnpx babel babel.js --presets=@babel/preset-env babelrc除了使用命令行配置 flag 之外,Babel 还支持配置文件,比如这里做的 ES6 语法转换,用到的是 babel-loader,这个 Loader 依赖@babel/core 和@babel/preset-env。然后在项目的根目录下,创建一个 babel 的配置文件.babelrc,内容如下: // .babelrc{ "presets": ["@babel/preset-env"]} Babel 会在正在被转义的文件当前目录中查找一个 .babelrc 文件。 如果不存在,它会向外层目录遍历目录树,直到找到一个 .babelrc 文件,或一个 package.json 文件中有 "babel": {}有了 babel-loader,可以使用 webpack 命令的—module-bind 来指定对应的文件需要经过怎样的 Loader 处理: "scripts": { "dev": "webpack --mode development ./src/index.js --module-bind js=babel-loader", "build": "webpack --mode production ./src/index.js --module-bind js=babel-loader"} env如果希望在不同的环境中使用不同的 Babel 配置,那么可以在配置文件中添加 env 选项,env 选项的值将从 process.env.BABEL_ENV 获取,如果没有的话,则获取 process.env.NODE_ENV 的值,它也无法获取时会设置为 “development”。 // .babelrc{ "env": { "production": { "presets": ["@babel/preset-env"] } }} pluginBabel 的插件分为两类:转换插件和语法解析插件。转换插件主要职责是进行语法转换,而解析插件则是扩展语法。 如果不想一个个的添加插件,那么可以使用插件组合 preset(插件预设,插件组合更加好理解一些),最常见的 preset 是@babel/preset-env。@babel/preset-env 是 Babel 官方推出的插件预设,它可以根据开发者的配置按需加载对应的插件。 如果在 ES5 中,有些对象、方法实际在浏览器中可能是不支持的,例如:Promise、Array.prototype.includes,这时候就需要用 @babel/polyfill 来做模拟处理。 // polyfill需要在文件内引入import '@babel/polyfill' s 3. @babel/polyfill 会直接修改内置的原型,且无法按需引入,可以使用@babel/runtime 的方案。 4. @babel/polyfill 和@babel/runtime 两种方式都比较繁琐,可以使用 @babel/preset-env 的 useBuildIns 选项做 polyfill,useBuiltIns 默认为 false,可以使用的值有 usage 和 entry // .babelrc{ "presets": [ ["@babel/preset-env", { "useBuiltIns": "usage|entry|false", "corejs": 3, "targets": { "browsers": "IE 10" } }] ]} usage 表示明确使用到的 Polyfill 引用,一般情况下 usage 就能满足日常开发。polyfill 用到的 core-js 是可以指定版本的,比如使用 core-js@3,则首先安装依赖 npm i -S core-js@3,然后在 Babel 配置文件.babelrc 中写上版本。使用 target 可以指定目标浏览器。 webpack 中使用 Babel// webpack.config.jsmodule.exports = { entry: './babel.js', mode: 'development', devtool: false, module: { rules: [ { test: /\.js$/, use: [ { loader: 'babel-loader', options: { presets: [ [ '@babel/preset-env', { useBuiltIns: 'usage', }, ], ], }, }, ], }, ], },} BrowserslistBrowserslist 用于设置目标浏览器的工具,声明一段浏览器的集合,工具可以根据这段集合描述,针对性的输出兼容性代码。Browserslist 的配置可以放在 package.json 中,也可以单独放在配置文件.browserslistrc 中。所有的工具都会主动查找 browserslist 的配置文件,根据 browserslist 配置找出对应的目标浏览器集合。 { "browserslist": ["last 2 version", "> 1%", "maintained node versions", "not ie < 11"]} # .browerslistrc# 每行一个浏览器集合描述last 2 version> 1%maintained node versionsnot ie < 11 范围 说明 last 2 versions 最新两个版本 > 1% 全球超过 1%人使用的浏览器,类似> 5% in US 则指代美国 5%以上用户 cover 99.5% 覆盖 99.5%主流浏览器 chrome > 50 ie 6-8 指定某个浏览器版本范围 Android/Chrome/Firefox/Baidu/Edge/Electron… unreleased versions 说有浏览器的 beta 版本 not ie < 11 排除 ie11 以下版本不兼容 since 2013 last 2 years 某时间范围发布的所有浏览器版本 maintained node versions 所有被 node 基金会维护的 node 版本 current node 当前环境的 node 版本 dead 全球使用率低于 0.5%且官方声明不在维护或者事实上已经两年没有再更新的版本 defaults 默认配置,> 0.5% last 2 versions Firefox ESR not dead 可以为不同的环境配置不同的目标浏览器。通过设置 BROWSERSLIST_ENV 或者 NODE_ENV 可以配置不同的环境变量。默认情况下会优先从 production 对应的配置项加载。在配置文件中,可以通过设置对应的环境目标浏览器: // package.json 写法{"browserslist": { "production": ["> 1%", "ie 10"], "development": ["last 1 chrome version", "last 1 firefox version"] }} #.browserslistrc:[production staging]> 1%> ie 10[development]last 1 chrome versionlast 1 firefox version]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Babel</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Webpack程序打包学习笔记(2)]]></title>
<url>%2F2020%2F07%2F05%2FWebpack_2%2F</url>
<content type="text"><![CDATA[Webpack externals,target,resolve,module,plugin,devtool 的配置。 Webpack 程序打包学习笔记(1)Webpack 程序打包学习笔记(2)Webpack 程序打包学习笔记(3) externalsexternals 配置项用于去除输出的打包文件中依赖的某些第三方 js 模块(例如 jquery,vue 等等),减小打包文件的体积。该功能通常在开发自定义 js 库(library)的时候用到,这些被依赖的模块应该由使用者提供,而不应该包含在 js 库文件中。 使用者依据 js 库的导出方式来提供依赖模块,如果没有设置 output.library, output.libraryTarget 等配置信息,那么以 <script> 标签的方式在页面中引入,被去除的依赖模块以全局变量的方式引入。导出方式为 commonjs/amd/umd 则被依赖模块以各自规范引入。 targetwebpack 中可以通过设置 target 来指定应用构建的目标(web/nodejs 服务/electron 应用…);target 的值有两种类型:string 和 function。 module.exports = { target: 'web', // 默认是 web,可以省略} const webpack = require('webpack')const options = { // function 类型,接收compiler作为参数 target: (compiler) => { compiler.apply( new webpack.JsonpTemplatePlugin(options.output), new webpack.LoaderTargetPlugin('web') ) },} string 类型支持下面的七种: web:默认,编译为类浏览器环境里可用; node:编译为类 Node.js 环境可用(使用 Node.js require 加载 chunk); async-node:编译为类 Node.js 环境可用(使用 fs 和 vm 异步加载分块); electron-main:编译为 Electron 主进程; electron-renderer:编译为 Electron 渲染进程; node-webkit:编译为 Webkit 可用,并且使用 jsonp 去加载分块。支持 Node.js 内置模块和 nw.gui 导入(实验性质); webworker:编译成一个 WebWorker。 resolveresolve 配置是帮助 Webpack 查找依赖模块,也可以替换对应的依赖。 常用的 resolve 配置: resolve.extensions:帮助 Webpack 解析扩展名的配置,默认值:[‘.wasm’, ‘.mjs’, ‘.js’, ‘.json’],所以我们引入 js 和 json 文件,可以不写它们的扩展名,通常我们可以加上 .css、.less 等,但是要确保同一个目录下面没有重名的 css 或者 js 文件。 resolve.alias:最常用的配置,通过设置 alias 可以缩短目录写法,帮助 webpack 更快查找模块依赖,也能使我们编写代码更加方便。设置了 alias,我们可以在任意文件中,不用理会目录结构,直接使用 require(‘@lib/utils’)或者 require(‘src/lib/utils’)来帮助 Webpack 定位模块。 module.exports = { resolve: { extensions: ['.js', '.json', '.css'], alias: { src: path.resolve(__dirname, 'src'), '@lib': path.resolve(__dirname, 'src/lib'), }, },} 设置 alias 会导致我们检测不到目录中的内容,不能帮我们快速编写代码,可以通过在项目根目录创建 jsconfig.json 来帮助我们定位 //jsconfig.json{ "compilerOptions": { "baseUrl": "./src", "paths": { "@lib/": ["src/lib"] } }} alias 还常被用于给生产环境和开发环境配置不同的 lib 库 module.exports = { resolve: { alias: { san: process.env.NODE_ENV === 'production' ? 'san/dist/san.min.js' : 'san/dist/san.dev.js', }, },} alias 还支持在名称末尾添加$符号来缩小范围只命中以关键字结尾的导入语句,这样可以做精准匹配: module.exports = { // 对 react 进行精确匹配 resolve: { alias: { react$: '/path/to/react.min.js', }, },} resolve.mainFields:针对不同宿主环境提供几份代码,例如提供 ES5 和 ES6 的两份代码,或者提供浏览器环境和 nodejs 环境两份代码 resolve.modules:查找模块依赖时,默认是 node_modules resolve.symlinks:是否解析符合链接(软连接,symlink) resolve.plugins:添加解析插件,数组格式 resolve.cachePredicate:是否缓存,支持 boolean 和 function,function 传入一个带有 path 和 require 的对象,必须返回 boolean 值 module在 webpack 解析模块的同时,不同的模块需要使用不同类型的模块处理器来处理,这部分的设置就在 module 配置中。module 有两个配置:module.noParse 和 module.rules module.rules 是在处理模块时,将符合规则条件的模块,提交给对应的处理器来处理,通常用来配置 loader,其类型是一个数组,数组里每一项都描述了如何去处理部分文件。每一项 rule 大致可以由以下三部分组成: 条件匹配:通过 test、include、exclude 配置命中可以应用规则的模块文件,匹配的对象包括三类: resource:请求文件的绝对路径 resourceQuery: ?之后的条件 issuer: 被请求资源的绝对路径,即导入时的位置 { // 来自src和test文件夹,不包含node_modules和bower_modules子目录,模块的文件路径为.tsx和.jsx结尾的文件 rules: [ test: [/\.jsx?$/, /\.tsx?$/], include: [ path.resolve(__dirname, 'src'), path.resolve(__dirname, 'test') ], exclude: [ path.resolve(__dirname, 'node_modules'), path.resolve(__dirname, 'bower_modules') ] ]} 应用规则:对匹配条件通过后的模块,使用 use 配置项来应用 loader,loader 是解析处理器,使用对应的 loader 之前,需要先安装它 // 指定*.less文件都是用less-loaderrules:[ test: /\.less$/, use:'less-loader'] 给 loader 传参的方式有两种:通过 options 传入和通过 query 的方式传入 // config内写法,通过 options 传入module: { rules: [ { test: /\.html$/, use: [ { loader: 'html-loader', options: { minimize: true, removeComments: false, collapseWhitespace: false, }, }, ], }, ]}// config内写法,通过 query 传入module: { rules: [ { test: /\.html$/, use: [ { loader: 'html-loader?minimize=true&removeComments=false&collapseWhitespace=false', }, ], }, ]} 执行顺序:一组 loader 的执行顺序默认是从后到前(或者从右到左)执行,通过 enforce 选项可以让其中一个 loader 的执行顺序放到最前(pre)或者是最后(post)。 // query 写法从右到左,使用!隔开const styles = require('css-loader!less-loader!./src/index.less')// 数组写法,从后到前module.exports = { module: { rules: [ { test: /\.less$/, use: [ { loader: 'style-loader', }, { loader: 'css-loader', }, { loader: 'less-loader', }, ], }, ], },} 如果需要调整 Loader 的执行顺序,可以使用 enforce,enforce 取值是 pre|post,pre 表示把放到最前,post 是放到最后: use: [ { loader: 'babel-loader', options: { cacheDirectory: true, }, // enforce:'post' 的含义是把该 loader 的执行顺序放到最后 // enforce 的值还可以是 pre,代表把 loader 的执行顺序放到最前 enforce: 'post', },] oneOf 表示对该资源只应用第一个匹配的规则,一般结合 resourceQuery,具体代码来解释: module.exports = { //... module: { rules: [ { test: /\.css$/, oneOf: [ { resourceQuery: /inline/, // foo.css?inline use: 'url-loader', }, { resourceQuery: /external/, // foo.css?external use: 'file-loader', }, ], }, ], },} module.noParse 配置项可以让 Webpack 忽略对部分没采用模块化的文件的递归解析和处理,这样做的好处是能提高构建性能,接收的类型为正则表达式,或者正则表达式数组或者接收模块路径参数的一个函数。一定要确定被排除出去的模块代码中不能包含 import、require、define 等内容,以保证 webpack 的打包包含了所有的模块,不然会导致打包出来的 js 因为缺少模块而报错。 module.exports = { module: { // 使用正则表达式 noParse: /jquery|lodash/ // 使用函数,从 Webpack 3.0.0 开始支持 noParse: (content) => { // content 代表一个模块的文件路径 // 返回 true or false return /jquery|lodash/.test(content); }}} pluginplugin 是 Webpack 的重要组成部分,可以直接通过 webpack 对象的属性来直接使用。loader 面向的是解决某个或者某类模块的问题,而 plugin 面向的是项目整体,解决的是 loader 解决不了的问题。 module.exports = { //.... plugins: [ // 压缩js new webpack.optimize.UglifyJsPlugin(); ]}// 除了内置的插件,我们也可以通过 NPM 包的方式来使用插件:const ExtractTextPlugin = require('extract-text-webpack-plugin');module.exports = { //.... plugins: [ // 导出css文件到单独的内容 new ExtractTextPlugin({ filename: 'style.css' }) ]}; devtooldevtool 是来控制怎么显示 sourcemap,通过 sourcemap 我们可以快速还原代码的错误位置]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Webpack</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Webpack程序打包学习笔记(1)]]></title>
<url>%2F2020%2F06%2F28%2FWebpack_1%2F</url>
<content type="text"><![CDATA[像 Grunt、Gulp 这类构建工具,打包的思路是:遍历源文件 → 匹配规则 → 打包,这个过程中做不到按需加载,即对于打包起来的资源,到底页面用不用,打包过程中是不关心的。 webpack 跟其他构建工具本质上不同之处在于:webpack 是从入口文件开始,经过模块依赖加载、分析和打包三个流程完成项目的构建。在加载、分析和打包的三个过程中,可以针对性的做一些解决方案,还可以轻松的解决传统构建工具解决的问题: 模块化打包,一切皆模块,JS 是模块,CSS 等也是模块;语法糖转换:比如 ES6 转 ES5、TypeScript;预处理器编译:比如 Less、Sass 等;项目优化:比如压缩、CDN;解决方案封装:通过强大的 Loader 和插件机制,可以完成解决方案的封装,比如 PWA;流程对接:比如测试流程、语法检测等。 webpack-cliWebpack-cli 是 Webpack 的 CLI (Command-line interface)工具,如果在项目中,可以使用下面的方式安装: npm install webpack-cli —save-dev如果想全局使用 webpack 的命令,可以使用 npm install -g webpack-cli 安装。Webpack 的打包环境有 production 和 development 两种,分别对应生产环境和开发环境,生产环境默认配置包括压缩等常用的配置。Webpack 默认的入口文件是 src/index.js;Webpack 的默认输出目录是 dist/main.js。 Tips:这里建议在项目中安装 webpack-cli 并且使用 —save-dev 的配置将 webpack-cli 放到开发依赖中。 "scripts": { "dev": "webpack --mode development", "build": "webpack --mode production"} 我们如果要修改 Webpack 的默认输出目录,需要用到 Webpack 命令的—output,我们将上面的 npm scripts 做下修改: "scripts": { "dev": "webpack --mode development --output ./output/main.js", "build": "webpack --mode production --output ./output/main.js"} webpack-cli 技巧: 当项目逐渐变大或者使用生产环境打包的时候,Webpack 的编译时间会变长,可以通过参数让编译的输出内容带有进度和颜色: webpack —progress —colors; Webpack 的配置比较复杂,很容出现错误,如果出问题,会打印一些简单的错误信息,我们还可以通过参数 —display-error-details 来打印错误详情:webpack —display-error-details; 如果不想每次修改模块后都重新编译,那么可以启动监听模式,开启监听模式后,没有变化的模块会在编译后缓存到内存中,而不会每次都被重新编译,所以监听模式的整体速度是很快的:webpack —watch; webpack-cli 支持两个快捷选项:-d 和 -p ,分别代表一些常用的开发环境和生产环境的打包。 常用 webpack 配置选项:–config:指定一个 Webpack 配置文件的路径;–mode:指定打包环境的 mode,取值为 development 和 production,分别对应着开发环境和生产环境;–json:输 mode 出 Webpack 打包的结果,可以使用 webpack —json > stats.json 方式将打包结果输出到指定的文件;–progress:显示 Webpack 打包进度;–watch, -w:watch 模式打包,监控文件变化之后重新开始打包;–color, —colors/–no-color, —no-colors:控制台输出的内容是否开启颜色;–hot:开启 Hot Module Replacement 模式,后面会详细介绍;–profile:会详细的输出每个环节的用时(时间),方便排查打包速度瓶颈。 配置 webpack.config.js可以通过修改 Webpack 的配置文件(webpack.config.js)来对 Webpack 进行配置,Webpack 的配置文件遵循 Node.js 的 CommonJS 模块规范Webpack 配置文件语法和类型多样,不仅支持 js 配置,还支持 ts(TypeScript)、CoffeeScript 甚至 JSX 语法的配置;除了使用对象类型,Webpack 还支持函数、Promise 和多配置数组。 // 基本配置const path = require('path')module.exports = { mode: 'development', entry: './index.js', output: { path: path.resolve(__dirname, 'dist'), filename: 'index.bundle.js', },} 如果只使用一个配置文件来区分生产环境(production)和开发环境(development),则可以使用函数类型的 Webpack 配置,函数类型的配置必须返回一个配置对象 Webpack 配置函数接受两个参数 env 和 argv:分别对应着环境对象和 Webpack-CLI 的命令行选项 module.exports = (env, argv) => { return { mode: env.production ? 'production' : 'development', devtool: env.production ? 'source-maps' : 'eval', plugins: [ new TerserPlugin({ terserOptions: { compress: argv['optimize-minimize'], // 只有传入 -p 或 --optimize-minimize }, }), ], }} 如果需要异步加载一些 Webpack 配置需要做的变量,那么可以使用 Promise 的方式来做 Webpack 的配置 module.exports = () => { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ entry: './app.js', /* ... */ }) }, 5000) })} 在一些特定的场景可能需要一次打包多次,而多次打包中有一些通用的配置,这时候可以使用配置数组的方式,将两次以上的 Webpack 配置以数组的形式导出 module.exports = [ { mode: 'production', // 配置1 }, { // 配置2 },] Webpack 配置 常见名词 参数 说明 entry 项目入口,包括字符串、对象、数组 module 开发中每一个文件都可以看做 module,模块不局限于 js,也包含 css、图片等 chunk 代码块,一个 chunk 可以由多个模块组成 loader 模块转化器,模块的处理器,对模块进行转换处理 plugin 扩展插件,插件可以处理 chunk,也可以对最后的打包结果进行处理,可以完成 loader 完不成的任务 bundle 最终打包完成的文件,一般就是和 chunk 一一对应的关系,bundle 就是对 chunk 进行便意压缩打包等处理后的产出 mode 指定开发环境打包 context 项目打包的相对路径,指定之后设置的 entry 和 output 的相对路径都是相对于 context;在实际开发中一般不需要配置 默认情况下,Webpack 会查找执行目录下面的 webpack.config.js 作为配置,如果需要指定某个配置文件,可以使用命令:webpack --config webpack.config.jsWebpack4.0 开始引入了 mode 配置,通过配置 mode=development 或者 mode=production 来制定是开发环境打包,还是生产环境打包除了在配置文件中设置 mode: module.exports = { mode: 'development',} 还可以在命令行中设置 mode:npm webpack --config webpack.config.entry.js --mode development entryentry 包括了单文件入口和多文件入口两种方式。单文件入口可以快速创建一个只有单一文件入口的情况,多文件入口是使用对象语法来通过支持多个 entry,具有较高的灵活性,可用于多页应用、页面模块分离优化。 // 单文件module.exports = { entry: 'index.js',}// 或者使用对象方式module.exports = { entry: { main: 'index.js', },}module.exports = { mode: 'development', entry: ['./src/app.js', './src/home.js'], output: { filename: 'array.js', },} 如果直接是 string 的形式,那么 webpack 就会直接把该 string 指定的模块(文件)作为入口模块 如果是数组 [string] 的形式,那么 webpack 会自动生成另外一个入口模块,并将数组中每个元素指定的模块(文件)加载进来,并将最后一个模块的 module.exports 作为入口模块的 module.exports 导出。 // 多文件module.exports = { entry: { home: 'home.js', search: 'search.js', list: 'list.js', },} outputoutput 的每一个 bundle 对应了 entry 的文件编译打包后的结果,output 的常用属性有: path此选项制定了输出的 bundle 存放的路径,比如 dist、output 等,不指定 output 时输出到 dist filename这个是 bundle 的名称,不指定 output 时输出为 dist/main.js publicPath指定了一个在浏览器中被引用的 URL 地址,当文件路径不同于他们的本地磁盘路径(由 output.path 指定)时,output.publicPath 被用来作为 src 或者 link 指向该文件。这种做法在需要将静态文件放在不同的域名或者 CDN 上面的时候是很有用的。 library如果打包生成一个供别人使用的库,那么可以使用 output.library 来指定库的名称,库的名称支持占位符和普通字符串:library: 'myLib' libraryTarget使用 output.libraryTarget 指定库打包出来的规范,取值范围为:var、assign、this、window、global、commonjs、commonjs2、commonjs-module、amd、umd、umd2、jsonp 一个 webpack 的配置,可以包含多个 entry,但是只能有一个 output,对于不同的 entry 可以通过 output.filename 占位符语法来区分。 module.exports = { entry: { home: 'home.js', search: 'search.js', list: 'list.js', }, output: { filename: '[name].js', // [name]为占位符,对应entry的key(home. search, list) path: __dirname + '/dist', publicPath: '/assets/', // CDN:publicPath: 'http://cdn.example.com/assets/' },} Webpack 目前支持的占位符: 占位符 含义 [hash] 模块标识符的 hash [chunkhash] chunk 内容的 hash [name] 模块名称 [id] 模块标识符 [query] 模块的 query,例如,文件名 ? 后面的字符串 [function] 一个 return 出一个 string 作为 filename 的函数 [name]:对应的是 entry 的 key(home、search、list…)[hash]:是整个项目的 hash 值,其根据每次编译内容计算得到,每次编译之后都会生成新的 hash,即修改任何文件都会导致所有文件的 hash 发生改变;在一个项目中虽然入口不同,但是 hash 是相同的;hash 无法实现前端静态资源在浏览器上长缓存,这时候应该使用 chunkhash[chunkhash]:根据不同的入口文件(entry)进行依赖文件解析,构建对应的 chunk,生成相应的 hash;只要组成 entry 的模块文件没有变化,则对应的 hash 也是不变的,所以一般项目优化时,会将公共库代码拆分到一起,因为公共库代码变动较少的,使用 chunkhash 可以发挥最长缓存的作用[hash] 和 [chunkhash] 的长度可以使用 [hash:16](默认为 20)来指定。或者,通过指定 output.hashDigestLength 在全局配置长度占位符是可以组合使用的,例如[name]-[hash:8] Webpack 程序打包学习笔记(2)Webpack 程序打包学习笔记(3)]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Webpack</tag>
</tags>
</entry>
<entry>
<title><![CDATA[BetterScroll插件实现页面滚动效果]]></title>
<url>%2F2020%2F05%2F28%2Fbetter-scroll%2F</url>
<content type="text"><![CDATA[  BetterScoll 用于解决列表的动态滚动,实现移动端列表上拉加载,下拉刷新,水平/垂直滚动,滚动至指定高度等功能。BetterScroll 支持大量参数配置,提供很多灵活的 api 实现指定功能。  实现 BetterScroll 滚动时父元素的高度或宽度需要进行固定,同时确保父元素和子元素内容正确渲染;在 DOM 结构发生改变时需要重新调用 scroll.refresh() 方法重新计算来确保滚动效果正常。 安装:npm install better-scroll --save 基本结构: <div class="wrapper"> <ul class="content"> <li>...</li> ... </ul> <!-- 其它的 DOM --></div><script> import BScroll from 'better-scroll' let scroll = new BScroll('.wrapper', { pullUpLoad: true, scrollbar: true, ... })</script> Scroll 配置项Scroll 常用方法Scroll 事件监听Vue 中实现 BetterScroll  Vue.js 提供了我们一个获取 DOM 对象的接口 vm.$refs,可以通过 this.$refs.wrapper 访问 DOM 对象。在 mounted 钩子函数里,使用回调函数保证初始化时 wrapper 的 DOM 已经渲染,可以正确计算它以及它内层 content 的高度以确保滚动正常。 <template> <div class="wrapper" ref="wrapper"> <ul class="content"> <li>...</li> <li>...</li> ... </ul> </div></template><script> import BScroll from 'better-scroll' export default { mounted() { this.$nextTick(() => { this.scroll = new Bscroll(this.$refs.wrapper, {}) }) }, }</script> 组件封装Scroll 组件的 DOM 结构包括顶部和底部的提示信息以及中间部分的列表组件,使用插槽 <slot> 进行占位。 <div ref="wrapper" class="wrapper"> <ul class="scroll-content"> <!-- 刷新提示信息 --> <div class="top-tip"> <span class="refresh-hook">{{pullDownMsg}}</span> </div> <!-- 内容列表 --> <slot></slot> <!-- 底部提示信息 --> <div class="bottom-tip"> <span class="loading-hook">'-到底了-'</span> </div> </ul></div> 组件的 js 部分对 Scroll 做 Vue 的封装,在 prop 里重写 Scroll 配置项,将控制权交给调用 Scroll.vue 的父组件;通过 methods 暴露的一些方法对 better-scroll 的方法做一层代理;watch 监听 data 的改变,及时调用 refresh 方法重新计算 better-scroll 确保滚动效果正常。 import BScroll from 'better-scroll'export default { // 常用配置和自定义配置 props: { probeType: { type: Number, default: 1 }, // 何时派发滚动事件 click: { type: Boolean, default: true }, // 点击时是否派发click事件 scrollX: { type: Boolean, default: false }, // 横向滚动 scrollY: { type: Boolean, default: false }, // 纵向滚动 bounce: { type: Boolean, default: false }, // 边缘弹回动画 autoBlur: { type: Boolean, default: false }, // 滚动之前激活元素失去焦点 // 自定义事件 pullup: { type: Boolean, default: false }, // 上拉动作触发事件 pulldown: { type: Boolean, default: false }, // 下拉动作出发事件 listenScroll: { type: Boolean, default: false }, // 监听滚动距离触发滚动事件 data: { type: Array, default: null }, // 父组件的列表数据 beforeScroll: { type: Boolean, default: false }, // 列表滚动开始事件 refreshDelay: { type: Number, default: 20 }, // 数据更新后刷新Scroll延时 showIcon: { type: Boolean, default: true }, // 下拉后显示返回按钮事件 toTop: { type: Boolean, default: false } // 返回顶部事件 ... }, methods: { _initScroll() { if (!this.$refs.wrapper) { return } // better-scroll的初始化 this.scroll = new BScroll(this.$refs.wrapper, { probeType: this.probeType, click: this.click,up scrollX: this.scrollX, pullup: this.pullup, pulldown: this.pulldown }) // 派发滚动事件,下拉一定距离后提示可刷新 if (this.listenScroll) { this.scroll.on('scroll', (pos) => { if (pos.y > 120) { this.pullDownMsg = '释放后进行刷新' } }) } // 执行下拉刷新操作 this.scroll.on('pullingDown', () => { this.$emit('pulldown') setTimeout(() => { this.scroll.finishPullDown() this.scroll.refresh() this.pullDownMsg = '-下拉刷新-' }, 600) }) // 派发列表滚动开始的事件 if (this.beforeScroll) { this.scroll.on('beforeScrollStart', () => { this.$emit('beforeScroll') }) } }, disable() { // 代理better-scroll的disable方法 this.scroll && this.scroll.disable() }, enable() { // 代理better-scroll的enable方法 this.scroll && this.scroll.enable() }, refresh() { // 代理better-scroll的refresh方法 this.scroll && this.scroll.refresh() }, scrollTo() { // 代理better-scroll的scrollTo方法 this.scroll && this.scroll.scrollTo.apply(this.scroll, arguments) }, scrollToElement() { // 代理better-scroll的scrollToElement方法 this.scroll && this.scroll.scrollToElement.apply(this.scroll, arguments) }, }, mounted() { // DOM渲染完毕后初始化better-scroll setTimeout(() => { this._initScroll() }, this.refreshDelay) }, watch: { // 监听数据的变化,延时refreshDelay时间后调用refresh方法重新计算,保证滚动效果正常 data() { setTimeout(() => { this.refresh() }, this.refreshDelay) }, },} 参考资料:https://github.com/ustbhuangyi/better-scrollhttps://better-scroll.github.io/docs/zh-CN/]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[swiper滑动插件]]></title>
<url>%2F2020%2F05%2F12%2Fswiper%2F</url>
<content type="text"><![CDATA[Swiper 和 vue-awesome-swiper 插件用于页面内容的触摸滑动,每个展示块为一个 slide,全部 slide 包含在包装器 wrapper 中,外部的总容器 container 又包裹着 wrapper 和箭头按钮控件 navigation 以及分页器控件 pagination。 <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> </div> <!--分页器。如果放置在swiper-container外面,需要自定义样式。--> <div class="swiper-pagination"></div> <!--左箭头。如果放置在swiper-container外面,需要自定义样式。--> <div class="swiper-button-prev"></div> <!--右箭头。如果放置在swiper-container外面,需要自定义样式。--> <div class="swiper-button-next"></div> <!-- 如果需要滚动条 --> <div class="swiper-scrollbar"></div></div> swiper初始结构import Swiper from 'swiper'var mySwiper = new Swiper('.swiper-container', { direction: 'vertical', // 垂直切换选项 loop: true, // 循环模式选项 ... // 如果需要分页器 pagination: { el: '.swiper-pagination', }, // 如果需要前进后退按钮 navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, // 如果需要滚动条 scrollbar: { el: '.swiper-scrollbar', },}) container 常用选项 initialSlide:初始化时显示的 slide,默认为第一个 slide direction:slide 滑动方向,默认为水平方向 speed:切换速度,单位 ms slidesPerView:设置同时显示的 slides 数量 slidesPerGroup:定义滑动时几个 slide 为一组 spaceBetween:在 slide 之间设置距离 loop:会在原本 slide 前后复制若干个 slide 并在合适的时候切换 preventClicks:防止滑动时执行链接跳转 touchRatio:设置触摸距离与 slide 滑动距离的比率 threshold:设置拖动临界值 touchAngle:设置触发拖动的角度值。默认 45 度,即使触摸方向不是完全水平也能拖动 slide autoplay:设置为 true 启动自动切换,可设置延迟 delay 参数 effect:设置切换效果,’slide’(普通切换、默认),”fade”(淡入)”cube”(方块)”coverflow”(3d 流)”flip”(3d 翻转) 组件功能 lazy:设为 true 开启图片延迟加载默认值 <!-- 延迟加载图片的结构 --><div class="swiper-slide"> <img data-src="path/to/picture-1.jpg" class="swiper-lazy" /> <div class="swiper-lazy-preloader"></div></div><script> var mySwiper = new Swiper('.swiper-container', { lazy: { loadPrevNext: true, }, })</script> zoom:开启焦距功能:双击 slide 会放大/缩小,并且在手机端可双指触摸缩放 <div class="swiper-slide"> <div class="swiper-zoom-container"> <img src="path/to/image" /> </div></div> thumbs:专门用于制作带缩略图的 swiper var thumbsSwiper = new Swiper('#thumbs', { spaceBetween: 10, slidesPerView: 4, watchSlidesVisibility: true, //防止不可点击})var gallerySwiper = new Swiper('#gallery', { spaceBetween: 10, thumbs: { swiper: thumbsSwiper, },}) 常用方法 mySwiper.slideNext(speed, runCallbacks) 滑动到下一个滑块 mySwiper.slidePrev(speed,runCallbacks) 滑动到前一个滑块 mySwiper.slideTo(index, speed, runCallbacks) 切换到指定 slide mySwiper.on(event,handler) 添加回调函数或者事件 vue-awesome-swipervue-awesome-swiper 是 vue 的 swiper 插件,npm install swiper vue-awesome-swiper --save安装导入后即可在组件中使用 /*main.js 全局安装*/import Vue from 'vue'import VueAwesomeSwiper from 'vue-awesome-swiper'// import style (>= Swiper 6.x)import 'swiper/swiper-bundle.css'// import style (<= Swiper 5.x)import 'swiper/css/swiper.css'Vue.use(VueAwesomeSwiper /* { default options with global component } */) /*.vue 组件内*/import { Swiper, SwiperSlide, directive } from 'vue-awesome-swiper'// import style (>= Swiper 6.x)import 'swiper/swiper-bundle.css'// import style (<= Swiper 5.x)import 'swiper/css/swiper.css'export default { components: { Swiper, SwiperSlide, }, directives: { swiper: directive, },} 初始结构<template> <swiper ref="mySwiper" :options="swiperOptions"> <swiper-slide>Slide 1</swiper-slide> <swiper-slide>Slide 2</swiper-slide> <swiper-slide>Slide 3</swiper-slide> <swiper-slide>Slide 4</swiper-slide> <swiper-slide>Slide 5</swiper-slide> <div class="swiper-pagination" slot="pagination"></div> </swiper></template><script>export default { name: 'carrousel', data() { return { swiperOptions: { pagination: { el: '.swiper-pagination' }, // Some Swiper option/callback... } } }, computed: { swiper() { return this.$refs.mySwiper.$swiper } }, methods: { ... }, mounted() { ... }}</script> 参考资料:https://www.swiper.com.cn/https://github.com/surmon-china/vue-awesome-swiper]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Vue</tag>
</tags>
</entry>
<entry>
<title><![CDATA[javascript异步,消息队列和事件循环]]></title>
<url>%2F2020%2F05%2F10%2Fjs%E5%90%8C%E6%AD%A5%E5%92%8C%E5%BC%82%E6%AD%A5%2F</url>
<content type="text"><![CDATA[  JavaScript 是单线程的,在 JS 引擎中负责解释和执行 JavaScript 代码的线程只有一个,而异步容易实现非阻塞,所以在 JavaScript 中对于耗时的操作或者时间不确定的操作,使用异步就成了必然的选择。 1. 异步过程异步过程:主线程发起一个异步请求 -> 工作线程接收请求(异步函数返回) -> 主线程继续执行后面的代码,同时工作线程执行异步任务 -> 工作线程完成工作后,通知主线程 -> 主线程收到通知后,执行一定的动作(调用回调函数)。 实现异步过程包括发起函数和回调函数,发起函数用于发起异步过程,回调函数用来处理调用的结果。 // 发起函数setTimeout(() => { // 回调函数内容}, 2000) 2. 消息队列和事件循环异步过程中,工作线程在异步操作完成后需要通知主线程。这个通知机制需要通过消息队列和事件循环完成。 消息队列是一个先进先出的队列,它里面存放着各种消息。JS 引擎线程执行栈中的同步任务,当所有同步任务执行完毕后,栈被清空,然后读取消息队列中的一个待处理任务,并把相关回调函数压入栈中执行新的同步任务。 每次栈被清空后,JS 引擎线程都会在消息队列中读取新的任务,如果没有新的任务,就会等待,直到有新的任务。 3. 异步编程方法 回调函数 将后者的执行改写为前者的回调函数。回调函数的优点是简单、容易理解和部署,缺点是不利于代码的阅读和维护,各个部分之间高度耦合(Coupling),流程会很混乱,而且每个任务只能指定一个回调函数。 function f1(callback) { //f1方法 setTimeout(() => { callback(f2) // f2执行改写为f1的回调函数 }, 1000)}function f2() { //f2方法} 常用的回调函数有 setTimeout,setInterval 和 nextTick setTimeout 设定为一段时间后执行异步任务,且在主线程执行完成后才被调用。 setInterval 是一个定时器函数,按照指定周期不断调用函数,在每次主线程完成后执行。常用于获取数据量过大的列表,先获取一部分用于 DOM 挂载和页面展示,之后再不断从后台获取全部数据。 process.nextTick() 是 Node.js 提供的异步执行函数,执行顺序会早于 setTimeout 和 setTimeInterval,在主线程完成后,任务队列调用之前执行,即在当前”执行栈”的尾部 -> 下一次 Event Loop(主线程读取”任务队列”)之前 -> 触发 process 指定的回调函数。 Promise 对象 ECMAscript 6 原生提供了 Promise 对象,代表了未来将要发生的事件,用来传递异步操作的消息,调用 resolve 或 reject 方法返回。 // 创建Promisevar promise = new Promise((resolve, reject) => { // 异步处理 if () { resolve(); } else { reject(); // 异步调用失败 }}) 对于已经实例化过的 promise 对象可以调用 promise.then() 方法,传递 resolve 和 reject 方法作为回调再判断结果,也可以调用 promise.catch()方法捕捉错误的回调函数。 promise .then( (res) => { // success }, (err) => { // error } ) .catch((err) => { // catch error }) 有了 Promise 对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise 对象提供统一的接口,使得控制异步操作更加容易。 async/await async/await 基于 Promise 实现,它不能用于普通的回调函数。使用 await,函数必须用 async 标识,await 后面跟的是一个 Promise 实例。 async function () { try{ const res1 = await f1(); const res2 = await f2(); ... } catch { // 处理报错 }}function f1 () { return new Promise ((resolve, reject) => { // f1方法 })}function f2 () { return new Promise ((resolve, reject) => { // f2方法 })} 参考资料:https://github.com/ljianshu/Blog/issues/53https://www.runoob.com/w3cnote/javascript-promise-object.html]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[json数据模拟]]></title>
<url>%2F2019%2F11%2F10%2Fjson-server%2F</url>
<content type="text"><![CDATA[  进行 web 网站开发时,前后端分离导致开发进度不同,前端经常需要等待后端的接口数据完成开发才可以继续调试。且开发环境,测试环境和线上环境分离,本地开发时无法运用测试环境的接口,开发时的接口和最终部署的接口也并不相同,每次测试时来回部署代码要耗费很多时间。  使用 json-server + mockjs 编写 json 格式的模拟数据接口,在等待后端准备接口期间,前端可以使用假数据进行模拟。 json-serverjson-server 是可以在本地运行,存储 json 数据的服务端。通过npm install -g json-server安装。 database.json 文件格式: { "data1": { "subdata1": "value1", "subdata2": "value2", "subdata3": "value3" }, "data2": {"subdata1": , "subdata2": , "subdata3": }, "data3": {"subdata1": , "subdata2": , "subdata3": }} 在配置完 json 文件后,使用json-server --watch --port 3001 database.json 命令,启动服务 database.json。访问localhost:3001可以查看 json 数据。 实现各类数据请求GET /GET|POST /postGET|POST /post/1GET /post?param1=&param2=GET /post/post?_page=1GET /posts?_sort=views&_order=ascGET /posts?_start=20&_end=30GET /posts?q=xxx // 搜索功能 自定义json-server 可以自定义路由,检验条件或输出格式 const jsonServer = require('json-server') // 创建json-server服务const server = jsonServer.create() // 创建http服务const router = jsonServer.router('db.js') // 路由匹配的js数据const middleWares = jsonServer.defaults() // 使用默认中间件server.use(jsonServer.bodyParser) // 安装json-server自带的body-parser,用于获取非地址栏传递的数据server.use(middleWares)server.use(router)// 监听自定义路由server.listen({ host: '192.168.137.1', post: 3000 }, () => { console.log('JSON Server is running')}) 其它功能: // 自定义js数据地址const path = require('path')const router = jsonServer.router(path.join(__dirname, 'db.json')) // 自定义注册操作// 注意: 自定义路由响应需要在安装json-server的router之前server.post( '/mock/register', ({ body: { username = '', password = '' } }, res) => { // console.log(username,password); username !== 'admin' && password ? res.jsonp({ err: 0, msg: '注册成功', data: { username, password, }, }) : res.jsonp({ err: 1, msg: '注册失败', }) }) // 增加检验条件 isAuthorizedserver.use((req, res, next) => { if (isAuthorized(req)) { // add your authorization logic here next() // continue to JSON Server router } else { res.sendStatus(401) }}) // 自定义返回内容router.render = (req, res) => { let status let len = Object.keys(res.locals.data).length // 判断是否获取到mockJS模拟的数据 if (res.req.originalMethod === 'DELETE') { status = len === 0 } else { status = !!len } setTimeout(() => { // 由于本地请求速度较快,不方便loading动效显示利用延时器,模拟真实服务器请求速度 res.jsonp({ // 使用res.jsonp()方法将mockJS模拟生成的数据进行自定义包装后输出 err: status ? 0 : 1, msg: '操作' + (status ? '成功' : '失败'), data: res.locals.data, }) }, 1000)} mockjsMock.js 是一款模拟数据生成器,可以根据数据模板生成模拟数据,模拟 Ajax 请求,基于 HTML 模板生成模拟数据。 // 安装npm install mockjs// 使用var Mock = require('mockjs');var data = Mock.mock({ ...}) Mock.js 使用数据模板定义生成模拟数据,数据模板中的每个属性由 3 部分构成:属性名、生成规则、属性值:'name|rule': value。也可以使用Mock.Random 工具类生成各种随机数据。具体语法在Mock.js 官网中有详细说明。 const Mock = require("mockjs"); // 引入mockJSconst MR = Mock.Random; // 提mock的随机对象module.exports = () => { let data = Mock.mock({ "home|5": [ { "id|+1": 1, "name": "@cname", "imgURL": MR.image('750X200',MR.color(),MR.cword(4,10)) ... }, ], ... }); return data;} webpack 配置数据地址 https://blog.csdn.net/qq_41629150/article/details/99645632https://github.com/typicode/json-server#getting-started Mock.js 官网json-server]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>JavaScript</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven POM 学习笔记]]></title>
<url>%2F2019%2F10%2F28%2Fmaven-pom%2F</url>
<content type="text"><![CDATA[POM( Project Object Model,项目对象模型 ) 是 Maven 工程的基本工作单元,是一个 XML 文件,包含了项目的基本信息,用于描述项目如何构建,声明项目依赖。POM 中可以指定以项目依赖,插件,执行目标,项目构建 profile,项目版本,项目开发者列表,相关邮件列表信息。所有 POM 文件都需要 project 元素和三个必需字段:groupId,artifactId,version。 1.Minimal POM最小 POM 需要 project 根标签和项目描述。 <!-- 工程根标签 --><project xmlns = "http://maven.apache.org/POM/4.0.0" xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <!-- 模型版本,对于Maven2及Maven 3来说,它只能是4.0.0 --> <modelVersion>4.0.0</modelVersion> <!-- 公司或者组织的唯一标志 --> <groupId>com.companyname.project-group</groupId> <!-- 项目的唯一ID,一个groupId下面可能多个项目,就是靠artifactId来区分的 --> <artifactId>project</artifactId> <!-- 工程版本号,区分同一个artifact的不同版本 --> <version>2.2.6.RELEASE</version> <!--项目产生的构件类型,包括jar、war、ear、pom等 --> <packaging>jar</packaging></project> 2.父(Super)POM父(Super)POM 是 Maven 默认的 POM。所有的 POM 都继承自一个父 POM,包含了一些可以被继承的默认设置。 <!-- 父项目工程模板 --><project> <!--依赖和扩展的远程仓库列表。 --> <repositories/> <!--插件的远程仓库列表,这些插件用于构建和报表 --> <pluginRepositories/> <!--构建项目需要的信息 --> <build/> <!--子项目可以引用的默认插件信息 --> <pluginManagement/> <!--报表规范--> <reporting/> <!--项目构建模板--> <profiles/></project> 3.POM 标签详解基于 POM 项目的基本<project/>结构,引入不同的标签定义不同的项目信息 parentparent 元素可以指定父 pom。用户可以通过增加 parent 元素来自定义一个父 pom,从而继承该 pom 的配置。parent 元素中包含一些子元素,用来定位父项目和父项目的 pom 文件位置。 <!--父项目的坐标 --><!--如果项目中没有规定某个元素的值,那么父项目中的对应值即为项目的默认值 --><parent> <!--被继承的父项目的构件标识符 --> <artifactId>com.companyname.project-group</artifactId> <!--被继承的父项目的全球唯一标识符 --> <groupId>base-project</groupId> <!--被继承的父项目的版本 --> <version>1.0.1-RELEASE</version> <!-- 父项目的pom.xml文件的相对路径,默认值是../pom.xml。 --> <relativePath>../pom.xml</relativePath></parent> 生成文档相关的元素maven 可以通过 mvn site 命令生成项目的相关文档,包括 name,url,和 description。 <!--项目的名称, Maven产生的文档用 --><name>kevin-maven</name><!--项目主页的URL, Maven产生的文档用 --><url>http://www.xxxxx.com/kevin</url><!-- 项目的详细描述, Maven 产生的文档用 --><description>A maven project to study maven.</description> issueManagement 项目的描述性信息问题管理<!--项目的问题管理系统--><issueManagement> <!--问题管理系统的名字, --> <system>question</system> <!--该项目使用的问题管理系统的URL --> <url>http://xxxxx.com/question</url></issueManagement> 开发者和贡献列表<!--项目开发者列表 --><developers> <!--某个项目开发者的信息 --> <developer> <id/> <name/> <email/> <url /> <roles> <role>Project Manager</role> <role>Architect</role> </roles> <organization/> <organizationUrl/> <!--项目开发者属性 --> <properties> <dept>No</dept> </properties> <!--项目开发者所在时区 --> <timezone/> </developer></developers> <!--项目的其他贡献者列表 --><contributors> <!--见developers/developer元素 --> ...</contributors> license 许可<licenses> <license> <name/> <!--官方的license正文页面的URL --> <url/> <!--项目分发的主要方式--> <distribution>repo</distribution> <!--关于license的补充信息 --> <comments/> </license></licenses> SCM 代码库控制管理<!--SCM(Source Control Management)标签允许你配置你的代码库,供Maven web站点和其它插件使用。 --><scm> <!--SCM的URL,该URL描述了版本库和如何连接到版本库。该连接只读 --> <connection>scm:svn:http://...</connection> <!--给开发者使用的,类似connection元素。即该连接不仅仅只读 --> <developerConnection>scm:svn:http://...</developerConnection> <!--当前代码的标签,在开发阶段默认为HEAD --> <tag /> <!--指向项目的可浏览SCM库(例如ViewVC或者Fisheye)的URL。 --> <url>http://...</url></scm> 项目组织描述<!--描述项目所属组织的各种属性。Maven产生的文档用 --><organization> <!--组织的全名 --> <name>demo</name> <!--组织主页的URL --> <url>http://xxx</url></organization> 创建时间<inceptionYear /> //4位数字。当产生版权信息时需要使用这个值 repositories 远程仓库远程仓库列表的配置,包括 <repositories> 依赖和扩展的远程仓库配置,以及 <pluginRepositories> 插件的远程仓库配置。在本地仓库找不到的情况下,maven 下载依赖、扩展和插件就是从这里配置的远程仓库中进行下载。其中 release 是稳定版本,一经发布不再修改,想发布修改后的项目,只能升级项目版本再进行发布;snapshot 是不稳定的,一个 snapshot 的版本可以不断改变。项目在开发期间一般会使用 snapshot,更方便进行频繁的代码更新;一旦发布到外部,或者开发基本完成,代码迭代不再频繁,则推荐使用 release。 <!--依赖和扩展的远程仓库列表。 --><repositories> <!--包含需要连接到远程仓库的信息 --> <repository> <!-- releases和snapshots两组配置,可以在每个单独的仓库中,为每种类型的构件采取不同的策略 --> <releases> <!-- true值为true或者false,表示该仓库是否为下载某种类型构件(发布版,快照版)开启。 --> <enabled /> <!-- 指定更新发生的频率。Maven会比较本地POM和远程POM的时间戳 --> <!--选项:always,daily(默认),interval:X(X单位为分钟),或者never。 --> <updatePolicy /> <!-- 当Maven验证构件校验文件失败时该怎么做。选项:ignore,fail,或者warn --> <checksumPolicy /> </releases> <snapshots> <enabled /> <updatePolicy /> <checksumPolicy /> </snapshots> <!-- 远程仓库唯一标识符。可以用来匹配在settings.xml文件里配置的远程仓库 --> <id>name-repository-proxy</id> <!-- 远程仓库名称 --> <name>name-repository-proxy</name> <!-- 远程仓库URL --> <url></url> <!-- 用于定位和排序构件的仓库布局类型。可以是default或者legacy --> <layout>default</layout> </repository></repositories><!--发现插件的远程仓库列表,这些插件用于构建和报表 --><pluginRepositories> <pluginRepository> ... </pluginRepository></pluginRepositories> dependencies 项目依赖pom 文件中通过 dependencyManagement 来声明依赖,通过 dependencies 元素来管理依赖。 <dependencies> <dependency> <!-- 依赖依赖坐标 --> <groupId>org.apache.maven</groupId> <artifactId>maven-artifact</artifactId> <version>3.8.1</version> <!-- 依赖类型,默认类型是jar --> <type>jar</type> <!-- 依赖的分类器 --> <classifier></classifier> <!-- 被排除的依赖,此元素主要用于解决版本冲突问题 --> <exclusions> <exclusion> <artifactId>spring-core</artifactId> <groupId>org.springframework</groupId> </exclusion> </exclusions> <!-- 可选依赖 --> <optional>true</optional> <!--依赖范围,在项目发布过程中,帮助决定哪些构件被包括进来 - compile:默认范围,用于编译 - provided:类似于编译,但支持jdk或者容器提供,类似于classpath - runtime: 在执行时需要使用 - systemPath: 仅用于范围为system。提供相应的路径 - test: 用于test任务时使用 - system: 需要外在提供相应的元素。通过systemPath来取得 - optional: 当项目自身被依赖时,标注依赖是否传递。用于连续依赖时使用 --> <scope></scope> </dependency></dependencies><dependencyManagement> <dependencies> <dependency> ... </dependency> </dependencies></dependencyManagement> build 项目构建需要的信息<build/>元素中包括 directory 路径管理,resource 资源管理,plugin 插件管理,extension 构建扩展等 路径管理路径管理定义了各种源码和编译结果的输出路径。如果遵循 maven 默认的路径约定,这里的几个元素不需要配置。 <!--项目源码目录,当构建项目的时候,构建系统会编译目录里的源码。该路径是相对于pom.xml的相对路径。 --><sourceDirectory /><!--该元素设置了项目单元测试使用的源码目录。该路径是相对于pom.xml的相对路径 --><testSourceDirectory /><!--被编译过的应用程序class文件存放的目录。 --><outputDirectory /><!--被编译过的测试class文件存放的目录。 --><testOutputDirectory /><!--项目脚本源码目录,该目录下的内容,会直接被拷贝到输出目录,因为脚本是被解释的,而不是被编译的 --><scriptSourceDirectory /> resource 资源管理<resources/>主要是对应用程序 resource 资源和单元测试部分 resource 资源的管理,分别通过 resource 标签和 testResource 标签管理两种资源。两个标签元素可选的子元素都是一样的。 <resources> <!-- 项目相关或测试相关的所有资源路径 --> <resource> <!-- 描述了资源的目标输出路径。该路径是相对于target/classes的路径 --> <targetPath /> <!--是否使用参数值代替参数名。参数值取自文件里配置的属性,文件在filters元素里列出。 --> <filtering /> <!--描述存放资源的目录,该路径相对POM路径 --> <directory /> <!--包含的模式列表,例如**/*.xml,只有符合条件的资源文件才会在打包的时候被放入到输出路径中 --> <includes /> <!--排除的模式列表,例如**/*.xml,符合的资源文件不会在打包的时候会被过滤掉 --> <excludes /> </resource></resources><!-- 单元测试相关的所有资源路径 --><testResources> <testResource> ... </testResource></testResources> plugin 插件管理插件包括 <pluginManagement/> 和 <plugins/>。<pluginManagement/> 中有子元素 <plugins/>,主要是用来声明子项目可以引用的默认插件信息,如果只写在 <pluginManagement/> 中是不会被引入的。<project/> 下的直接子元素 <plugins/> 中定义的才是这个项目中真正需要被引入的插件。 <!-- 子项目可以引用的默认插件信息。pluginManagement中的插件直到被引用时才会被解析或绑定到生命周期 --><!-- 这里只是做了声明,并没有真正的引入。给定插件的任何本地配置都会覆盖这里的配置--><pluginManagement> <!-- 可使用的插件列表 --> <plugins> <!--plugin元素包含描述插件所需要的信息。 --> <plugin> <!--插件定位坐标三元素:groupId + artifactId + version --> <groupId /> <artifactId /> <version /> <!-- 是否使用这个插件的Maven扩展(extensions),默认为false --> <!-- 由于性能原因,只有在真需要下载时,该元素才被设置成enabled --> <extensions /> <!--在构建生命周期中执行一组目标的配置。每个目标可能有不同的配置。 --> <executions> <!--execution元素包含了插件执行需要的信息 --> <execution> <!--执行目标的标识符 --> <id /> <!--绑定目标的构建生命周期阶段 --> <phase /> <!--配置的执行目标 --> <goals /> <!--配置是否被传播到子POM --> <inherited /> <!--作为DOM对象的配置 --> <configuration /> </execution> </executions> <!--项目引入插件所需要的额外依赖 --> <dependencies/> <!--任何配置是否被传播到子项目 --> <inherited /> <!--作为DOM对象的配置 --> <configuration /> </plugin> </plugins></pluginManagement> <!--project使用的插件列表 --><plugins><!-- 可选的子元素同上 --> <plugin/></plugins> extension 构建扩展<extensions/> 是在此构建中使用的项目的列表,它们将被包含在运行构建的 classpath 中。这些项目可以启用对构建过程的扩展,并使活动的插件能够对构建生命周期进行更改。简而言之,扩展是在构建期间激活的 artifacts。 <extensions> <extension> <!--项目坐标三元素:groupId + artifactId + version --> <groupId /> <artifactId /> <version /> </extension></extensions> 其它配置<!--当项目没有规定目标(Maven2 叫做阶段)时的默认值 --><defaultGoal /><!--构建产生的所有文件存放的目录 --><directory /><!--产生的构件的文件名,默认值是${artifactId}-${version}。 --><finalName /><!--当filtering开关打开时,使用到的过滤器属性文件列表 --><filters /> profile 配置定义项目构建的模板,当有条件被激活时会修改构建处理 <!--在列的项目构建profile,如果被激活,会修改构建处理 --><profiles> <!--根据环境参数或命令行参数激活某个构建处理 --> <profile> <!--构建配置的唯一标识符。即用于命令行激活,也用于在继承时合并具有相同标识符的profile。 --> <id /> <!-- 自动触发profile的条件逻辑 --> <activation> <!--profile默认是否激活的标志 --> <activeByDefault /> <!--当匹配的jdk被检测到,profile被激活 --> <jdk /> <!--os元素可以定义一些操作系统相关的属性。 --> <os> <!--激活profile的操作系统的名字 --> <name>Windows XP</name> <!--激活profile的操作系统所属家族(如 'windows') --> <family>Windows</family> <!--激活profile的操作系统体系结构 --> <arch>x86</arch> <!--激活profile的操作系统版本 --> <version>5.1.2600</version> </os> <!--如果Maven检测到某一个属性,其拥有对应的名称和值,Profile就会被激活 --> <property> <!--激活profile的属性的名称 --> <name>mavenVersion</name> <!--激活profile的属性的值 --> <value>2.0.3</value> </property> <!--提供一个文件名,通过检测该文件的存在或不存在来激活profile。missing检查文件是否存在,如果不存在则激活profile --> <!--另一方面,exists则会检查文件是否存在,如果存在则激活profile --> <file> <!--如果指定的文件存在,则激活profile。 --> <exists>/usr/local/abcd/abcd-home/jobs/maven-guide-zh-to-production/workspace/ </exists> <!--如果指定的文件不存在,则激活profile。 --> <missing>/usr/local/abcd/abcd-home/jobs/maven-guide-zh-to-production/workspace/ </missing> </file> </activation> <build /> <repositories /> <pluginRepositories /> <dependencies /> <dependencyManagement /> <reporting /> <distributionManagement /> <modules /> <properties /> </profile></profiles> distributionManagement 项目分发信息相关元素<distributionManagement> <!--部署项目产生的构件到远程仓库需要的信息 --> <repository> <!-- 是分配给快照一个唯一的版本号 --> <uniqueVersion /> <id>kevin-maven2</id> <name>kevinmaven2</name> <url>file://${basedir}/target/deploy</url> <layout /> </repository> <!-- 构件临时部署的仓库 --> <snapshotRepository/> <repository> ... <repository/> </snapshotRepository> <!--部署项目的网站需要的信息 --> <site> <!--部署位置的唯一标识符,用来匹配站点和settings.xml文件里的配置 --> <id>kevin-site</id> <!--部署位置的名称 --> <name>website</name> <!--部署位置的URL,按protocol://hostname/path形式 --> <url/> </site> <!--项目下载页面的URL。如果没有该元素,用户应该参考主页 --> <!--本元素是为了帮助定位那些不在仓库里的构件(license限制) --> <downloadUrl /> <!--如果构件移到了新的位置,这里列出构件的重定位信息 --> <relocation> <groupId /> <artifactId /> <version /> <!--显示给用户的,关于移动的额外信息,例如原因 --> <message /> </relocation> <!-- 给出该构件在远程仓库的状态。本地项目中不能设置该元素,因为这是工具自动更新的 --> <!-- 有效的值有:none(默认),converted(仓库管理员从 Maven 1 POM转换过来), partner(直接从伙伴Maven 2仓库同步过来),deployed(从Maven 2实例部署), verified(被核实时正确的和最终的) --> <status /></distributionManagement> reporting 报表规范报表规范描述的是使用 mvn site 命令时使用的一些配置 <!-- 执行"mvn site"运行报表 --><reporting> <!--网站是否排除默认的报表。这包括"项目信息"菜单中的报表。 --> <excludeDefaults /> <!--所有产生的报表存放到哪里。默认值是${project.build.directory}/site。 --> <outputDirectory /> <!--使用的报表插件和他们的配置。 --> <plugins> <!--plugin元素包含描述报表插件需要的信息 --> <plugin> <groupId /> <artifactId /> <version /> <inherited /> <configuration /> <!-- 一组报表的多重规范,每个规范可能有不同的配置。一个规范(报表集)对应一个执行目标 --> <reportSets> <!--表示报表的一个集合,以及产生该集合的配置 --> <reportSet> <!--报表集合的唯一标识符,POM继承时用到 --> <id /> <!--产生报表集合时,被使用的报表的配置 --> <configuration /> <!--配置是否被继承到子POMs --> <inherited /> <!--这个集合里使用到哪些报表 --> <reports /> </reportSet> </reportSets> </plugin> </plugins></reporting> 邮件列表<!--项目相关邮件列表信息 --><mailingLists> <mailingList> <!--邮件的名称 --> <name>Demo</name> <!--发送邮件的地址或链接 --> <post>[email protected]</post> <!--订阅邮件的地址或链接 --> <subscribe>[email protected]</subscribe> <!--取消订阅邮件的地址或链接 --> <unsubscribe>[email protected]</unsubscribe> <!--你可以浏览邮件信息的URL --> <archive>http:/xxxxxx/kevin/demo/</archive> </mailingList></mailingLists> ciManagement 持续集成配置<!--项目持续集成信息 --><ciManagement> <!--持续集成系统的名字,例如continuum --> <system /> <!--该项目使用的持续集成系统的URL(如果持续集成系统有web接口的话)。 --> <url /> <!--构建完成时,需要通知的开发者/用户的配置项。包括被通知者信息和通知条件(错误,失败,成功,警告) --> <notifiers> <!--配置一种方式,当构建中断时,以该方式通知用户/开发者 --> <notifier> <!--传送通知的途径 --> <type /> <!--发生错误时是否通知 --> <sendOnError /> <!--构建失败时是否通知 --> <sendOnFailure /> <!--构建成功时是否通知 --> <sendOnSuccess /> <!--发生警告时是否通知 --> <sendOnWarning /> <!--不赞成使用。通知发送到哪里 --> <address /> <!--扩展配置项 --> <configuration /> </notifier> </notifiers></ciManagement> 其他配置<!--描述了这个项目构建环境中的前提条件。 --><prerequisites> <!--构建该项目或使用该插件所需要的Maven的最低版本 --> <maven /></prerequisites><!--模块被构建成项目的一部分。列出的每个模块元素是指向该模块的目录的相对路径 --><modules /> POM 主要配置结构project: modelVersion, artifactId, packing, version, name, url, description, inceptionYear|-- prerequisites: maven|-- *parent: artifactId, groupId, version, relativePath|-- *repositories: repository| |-- id, name, url, layout| release| |-- enabled, updatePolicy, checksumPolicy| snapshot| |-- enabled, updatePolicy, checksumPolicy|-- *pluginRepositories: pluginRepository(同repositories)|-- *dependencies: dependency| |-- artifactId, groupId, version, type, classifier, scope, systemPath, optional| executions| |-- exclusion| |-- artifactId, groupId|-- *build: sourceDirectory, scriptCourceDirectory, testSourceDirectory, outputDirectory, testOutputDirectory,| extensions, defaultGoal, directory, finalName, filters| |-- groupId, artifactId, version| resources| |-- resource| |-- targetPath, filtering, directory, includes, excludes| testResources| |-- testResource| |-- targetPath, filtering, directory, includes, excludes| pluginManagement| |-- plugins| |-- plugin| |-- groupId, artifactId, version, extensions, inherited, configuration| executions| |-- execution| |-- id, phase, goals, inherited, configuration| dependencies(同project/dependencies)| plugins(同pluginManagement/plugins)|-- *reporting: excludeDefaults, outputDirectory| plugin| |-- groupId,artifactId, version, extensions, goals, inherited, configuration| reportSets| |-- reportSet| |-- id, configuration, inherited|-- *dependencyManagement: dependencie(同project/dependencies)|-- *distributionManagement: repository, downloadUrl, status| |-- uniqueVersion, id, name, url, layout| snaphotRepository| |-- uniqueVersion, id, name, url, layout| site| |-- id, name, url| relocation| |-- groupId, artifactId, version, message|-- *profiles: profile| |-- id, activation, modules| |-- activeByDefault, jdk, property,| os| |-- name, family, arch, version| file| |-- exists, missing| build(同project/build)|||-- developers: developer| |-- id, name, email, url, roles, organization, organizationUrl, properties, timezone|-- contributors: contributor| |-- name, email, url, roles, organization, organizationUrl, properties, timezone|-- licenses: license| |-- name, url, distribution, comments|-- scm: connection, developerConnection, tag, url|-- organization: name, url|-- mailingLists: mailingList| |-- name, post, subscribe, unsubscribe, archive|-- issueManagement: system, url|-- ciManagement: system, url, notifiers| |-- type, sendOnError, sendOnFailure, sendOnSuccess, sendOnWarning, address, configuration]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>Maven</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Maven 项目构建笔记]]></title>
<url>%2F2019%2F10%2F13%2Fmaven-lifecycle%2F</url>
<content type="text"><![CDATA[Maven 可以统一集中管理所有的依赖包,并且能够自动解决重复和冲突问题。Maven 作为一个开放的架构,方便同第三方插件集成。 Maven 配置文件构建配置文件可以用来设置或者覆盖 Maven 构建默认值,可以为不同的生产环境(Production)和开发(Development)环境定制构建方式。 类型 配置文件定义 项目级(Per Project) 定义在项目的 POM 文件 pom.xml 中 用户级 (Per User) 定义在 Maven 的设置 xml 文件中 (%USER_HOME%/.m2/settings.xml) 全局(Global) 定义在 Maven 全局的设置 xml 文件中 (%M2_HOME%/conf/settings.xml) 编写和激活配置文件在 src/main/resources 文件夹下有三个配置,env.properties 为默认配置,env.test.properties 为测试配置文件,env.prod.properties 为生产配置。配置文件在 pom.xml 文件中使用 activeProfiles 或者 profiles 元素指定,并且可以通过各种方式触发。 1.配置文件中设置可以使用 pom.xml 来定义不同的 profile,并在命令控制台中使用 maven 命令激活 profile。 <!--默认配置构建,开发和测试配置格式也相同, <id> 区分不同的 <profiles> 执行不同的 AntRun 任务--><profiles> <profile> <id>normal</id> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-antrun-plugin</artifactId> <version>1.8</version> <executions> <execution> <phase>test</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>Using env.properties</echo> <copy file="src/main/resources/env.properties" tofile="${project.build.outputDirectory}/env.properties" overwrite="true"/> </tasks> </configuration> </execution> </executions> </plugin> </plugins> </build> </profile></profiles> 2.通过 maven 设置打开 %USER_HOME%/.m2 目录下的 settings.xml 文件配置 setting.xml <settings> ... <activeProfiles> <activeProfile>test</activeProfile> </activeProfiles></settings> 3.基于环境变量设置在 pom.xml 里面的 <id> 为 test 的 <profile> 节点,加入 <activation> 节点 <profiles> <profile> <id>test</id> <activation> <property> <name>env</name> <value>test</value> </property> </activation> <build/> </profile></profiles> 4.操作系统设置在 activation 元素里包含操作系统信息 <activation> <os> <name>Windows XP</name> <family>Windows</family> <arch>x86</arch> <version>5.1.2600</version> </os></activation> 5.文件的存在或者缺失时触发在 activation 里设置缺失条件时触发配置 <activation> <file> <missing>target/generated-sources/...</missing> </file></activation> maven 生命周期Maven 三个标准的生命周期:clean 项目清理的处理;default 项目部署的处理;site 项目站点文档创建的处理在一个 Maven 生命周期中,运行某个阶段的时候,它之前的所有阶段都会被运行。 1.cleanpre-clean:执行一些需要在 clean 之前完成的工作clean:移除所有上一次构建生成的文件post-clean:执行一些需要在 clean 之后立刻完成的工作 目标在生命周期中执行 <!-- pre-clean配置, clean, post-clean格式相同 --><executions> <execution> <id>id.pre-clean</id> <phase>pre-clean</phase> <goals> <goal>run</goal> </goals> <configuration> <tasks> <echo>pre-clean phase</echo> </tasks> </configuration> </execution></executions> 2.default / buildMaven 的主要生命周期,被用于构建应用,包括 23 个构建阶段 生命周期阶段 描述 validate(校验) 校验项目是否正确并且所有必要的信息可以完成项目的构建过程。 initialize(初始化) 初始化构建状态,比如设置属性值。 generate-sources(生成源代码) 生成包含在编译阶段中的任何源代码。 process-sources(处理源代码) 处理源代码,比如说,过滤任意值。 generate-resources(生成资源文件) 生成将会包含在项目包中的资源文件。 process-resources (处理资源文件) 复制和处理资源到目标目录,为打包阶段最好准备。 compile(编译) 编译项目的源代码。 process-classes(处理类文件) 处理编译生成的文件,比如说对 Java class 文件做字节码改善优化。 generate-test-sources(生成测试源代码) 生成包含在编译阶段中的任何测试源代码。 process-test-sources(处理测试源代码) 处理测试源代码,比如说,过滤任意值。 generate-test-resources(生成测试资源文件) 为测试创建资源文件。 process-test-resources(处理测试资源文件) 复制和处理测试资源到目标目录。 test-compile(编译测试源码) 编译测试源代码到测试目标目录. process-test-classes(处理测试类文件) 处理测试源码编译生成的文件。 test(测试) 使用合适的单元测试框架运行测试(Juint 是其中之一)。 prepare-package(准备打包) 在实际打包之前,执行任何的必要的操作为打包做准备。 package(打包) 将编译后的代码打包成可分发格式的文件,比如 JAR、WAR 或者 EAR 文件。 pre-integration-test(集成测试前) 在执行集成测试前进行必要的动作。比如说,搭建需要的环境。 integration-test(集成测试) 处理和部署项目到可以运行集成测试环境中。 post-integration-test(集成测试后) 在执行集成测试完成后进行必要的动作。比如说,清理集成测试环境。 verify (验证) 运行任意的检查来验证项目包有效且达到质量标准。 install(安装) 安装项目包到本地仓库,这样项目包可以用作其他本地项目的依赖。 deploy(部署) 将最终的项目包复制到远程仓库中与其他开发者和项目共享。 添加执行的方法同 clean 3.siteMaven Site 插件一般用来创建新的报告文档、部署站点等 pre-site:执行一些需要在生成站点文档之前完成的工作site:生成项目的站点文档post-site: 执行一些需要在生成站点文档之后完成的工作,并且为部署做准备site-deploy:将生成的站点文档部署到特定的服务器上 添加执行的方法同 clean Maven 项目构建命令行方法Maven 使用原型 archetype 插件创建项目 mvn archetype:generate清理目标目录 mvn clean编译源代码 mvn compile运行测试案例 mvn test打包项目构建的输出为 jar(package)文件 mvn clean package安装 mvn install创建项目文档 mvn site,在 \target\site 文件夹。点击 index.html 查看文档生成 API Doc 文档 mvn javadoc:javadoc,工程中自动产生 target\site\apidocs 目录,index.html 查看文档 pom.xml 中添加插件常用项目构建插件 插件名称 用途 maven-clean-plugin 清理项目 maven-compile-plugin 编译项目 maven-deploy-pligin 发布项目 maven-site-plugin 生成站点 maven-surefire-plugin 运行测试 maven-jar-plugin 构建 jar 项目 maven-javadoc-plugin 生成 javadoc 文件 maven-surefire-report-plugin 生成测试报告 用浏览器打开 Maven Repository 可以查看插件的最新版本,单击 Search 按钮,然后在 pom.xml 中添加 build 标签,描述插件信息 <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-xxx-plugin</artifactId> <version></version> <configuration> <!-- 设置包含的类 --> <includes> <include>....</include> </includes> <!-- 设置不执行的类 --> <excludes> <exclude>...</exclude> </excludes> </configuration> </plugin> </plugins></build>]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>Maven</tag>
</tags>
</entry>
<entry>
<title><![CDATA[iview_note 学习笔记(3) —— 布局]]></title>
<url>%2F2019%2F09%2F20%2Fiview-note-3%2F</url>
<content type="text"><![CDATA[Loading… iview 布局提供了比较便捷的网页架构排版,可以省去很多页面样式的调试。 iview_note 学习笔记(1)iview_note 学习笔记(2) 布局List<template> <List header="Header" footer="Footer" border> <ListItem>This is a piece of text.</ListItem> <!--基础用法--> <ListItem> <ListItemMeta avatar="https://dev-file.iviewui.com/userinfoPDvn9gKWYihR24SpgC319vXY8qniCqj4/avatar" title="This is title" description="This is description." /> <!--带有图标、标题、描述的基础列表--> <!--可以带有列表操作组--> <template slot="action"> <li> <a href="">Edit</a> </li> <li> <a href="">More</a> </li> </template> <!--可以带有图片--> <template slot="extra" ><!--额外内容展示在右侧--> <img src=" " style="width: 280px" /> </template> </ListItem> </List></template> 设置属性 size (small、large、default) 可以显示三种不同尺寸的列表。设置 border 是否显示边框设置 header 或 footer 来自定义列表头部或尾部。 设置属性 item-layout 为 vertical 可实现竖排列表样式 <template> <List item-layout="vertical"> <ListItem v-for="item in data" :key="item.title"> <ListItemMeta :avatar="item.avatar" :title="item.title" :description="item.description" /> {{ item.content }} <template slot="action"> <li><Icon type="ios-star-outline" /> 123</li> <li><Icon type="ios-thumbs-up-outline" /> 234</li> <li><Icon type="ios-chatbubbles-outline" /> 345</li> </template> </ListItem> </List></template><script> export default { data() { return { data: [ { title: 'This is title 1', description: 'This is description.', avatar: '', content: 'this is the content.', }, { title: 'This is title 2', description: 'This is description.', avatar: '', content: 'this is the content.', }, ], } }, }</script> Card<template> <Card style="width:350px"> <p slot="title"> <Icon type="ios-film-outline"></Icon> Classic film </p> <a href="#" slot="extra" @click.prevent="changeLimit"> <Icon type="ios-loop-strong"></Icon> Change </a> <ul> <li v-for="item in randomMovieList"> <a :href="item.url" target="_blank">{{ item.name }}</a> </li> </ul> </Card></template><script> export default { data () { return { movieList: [ { name: 'The Shawshank Redemption', url: 'https://', }, { name: 'Leon:The Professional', url: 'https://', }, { name: 'Farewell to My Concubine', url: 'https://', } ], randomMovieList: [] } }</script> 设置 title 和 extra 可以定义卡片标题和右上角额外内容 Row 和 Col 格式实现并排表格 <Row style="width:350px"> <Col span="11"> <Card> <p slot="title">The standard card</p> <p>Content of card</p> </Card> </Col> <Col span="11" offset="2"> <Card dis-hover> <p slot="title">Disable card with hover shadows</p> <p>Content of card</p> </Card> </Col></Row> Collapse<template> <Collapse v-model="value1"> <Panel name="1"> name1 <p slot="content">message1</p> </Panel> <Panel name="2"> name2 <p slot="content">message2</p> </Panel> </Collapse></template><script> export default { data() { return { value1: '1', } }, }</script> 设置属性 accordion 开启手风琴模式,每次只能打开一个面板设置属性 simple 可以显示为不带边框和背景色的简洁模式 Split左右分割 <div class="demo-split"> <Split v-model="split1"> <div slot="left" class="demo-split-pane">Left Pane</div> <div slot="right" class="demo-split-pane">Right Pane</div> </Split></div><script> export default { data() { return { split1: 0.5, // 控制分割的量 } }, }</script> top button 可实现上下分割,也可以使用嵌套分割 Divider<Divider /><Divider dashed /><Divider>With Text</Divider> 使用 type=”vertical” 设置为行内的垂直分割线使用 orientation 设置分割线标题的位置,可选值为 left、right 或 center Cell<Cell title=" " />可设置 name(标识) title(左侧标题) label(描述信息) extra(右侧额外内容) disabled(禁用) selscted(选中) to(跳转) 属性 LayoutLayout:布局容器,其下可嵌套 HeaderSiderContentFooter 或 Layout 本身,可以放在任何父容器中Header:顶部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中Sider:侧边栏,自带默认样式及基本功能,其下可嵌套任何元素,只能放在 Layout 中Content:内容部分,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中Footer:底部布局,自带默认样式,其下可嵌套任何元素,只能放在 Layout 中 <div class="layout"> <Layout> <Sider hide-trigger>Sider</Sider> <header>Header</header> <content>Content</content> <footer>Footer</footer> </Layout></div> Grid LoadingBar Badge 视图图表]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>iview</tag>
</tags>
</entry>
<entry>
<title><![CDATA[iview_note 学习笔记(2) —— 表单]]></title>
<url>%2F2019%2F08%2F23%2Fiview-note-2%2F</url>
<content type="text"><![CDATA[iview 表单处理模板 iview_note 学习笔记(1)iview_note 学习笔记(3) Input<Input v-model="value" placeholder="Enter something..." /> <!--使用 v-model 实现数据的双向绑定--><Input v-model="value1" size="large" placeholder="large size" /> <!--设置size为large和small设置为大和小尺寸--><Input v-model="value2" placeholder="Enter something..." clearable /> <!--开启属性 clearable 可显示清空按钮--><Input v-model="value3" maxlength="100" /> <!--设置最大字数--><Input v-model="value4" icon="ios-clock-outline" /> <!--icon 属性可以在输入框右边加一个图标--><!--通过设置 prefix 和 suffix 及同名 slot 设置前缀及后缀图标--><Input prefix="ios-contact" placeholder="Enter name" style="width: auto" /><Input suffix="ios-search" placeholder="Enter text" style="width: auto" /><Input placeholder="Enter name" style="width: auto"> <Icon type="ios-contact" slot="prefix" /></Input><Input placeholder="Enter text" style="width: auto"> <Icon type="ios-search" slot="suffix" /></Input><Input search placeholder="Enter something..." /> <!--开启 search 属性--> 使用 v-model 实现数据的双向绑定设置 size 为 large 和 small 设置为大和小尺寸开启属性 clearable 可显示清空按通过 icon 属性可以在输入框右边加一个图标,点击图标,会触发 on-click 事件 Radio<Radio v-model="single">Radio</Radio><!--组合使用--><RadioGroup v-model="phone"> <Radio label="apple"> <Icon type="logo-apple"></Icon> apple </Radio> <Radio label="android"> <Icon type="logo-android"></Icon> android </Radio> <Radio label="windows"> <Icon type="logo-windows"></Icon> windows </Radio></RadioGroup> 可设置 disabled 属性来禁用单选框设置属性 size 为 large 或 small 将按钮样式设置为大和小尺寸设置属性 type 为 button 来应用按钮的样式设置 vertical 属性来垂直显示 Checkbox<Checkbox v-model="single">Checkbox</Checkbox><!--组合使用--><CheckboxGroup v-model="social"> <Checkbox label="twitter"> <Icon type="logo-twitter"></Icon> <span>Twitter</span> </Checkbox> <Checkbox label="facebook"> <Icon type="logo-facebook"></Icon> <span>Facebook</span> </Checkbox> <Checkbox label="github"> <Icon type="logo-github"></Icon> <span>Github</span> </Checkbox></CheckboxGroup> 相关属性同 Radio Switch<i-switch v-model="switch1" @on-change="change"> <span slot="open">开</span> <span slot="close">关</span></i-switch> 可以使用 disabled size 属性 可以使用 loading 标识开关操作仍在执行中 Table<template> <table :columns="columns1" :data="data1"></table></template><script> export default { data () { return { columns1: [ { type: 'selection', width: 60, align: 'center', sortable: true { title: 'Name', key: 'name' }, { title: 'Age', key: 'age', filters: [ { label: 'Greater than 25', value: 1 }, { label: 'Less than 25', value: 2 } ] }, { title: 'Address', key: 'address' } ], data1: [ { name: 'name1', age: 18, address: ' ', date: '2019' }, { name: 'Jim Green', age: 24, address: ' ', date: '2019' }, { name: 'Joe Black', age: 30, address: ' ', date: '2019' } ] } } }</script> 指定样式: 通过属性 row-class-name 可以给某一行指定一个样式名称。 通过给列 columns 设置字段 className 可以给某一列指定一个样式。 通过给数据 data 设置字段 cellClassName 可以给任意一个单元格指定样式。 指定数据设置: 给 columns 数据设置一项,指定 type: ‘selection’,即可自动开启多选功能 给 columns 数据的项,设置 sortable: true,即可对该列数据进行排序 给 columns 数据的项,设置 filters,可进行筛选,filterMethod 传入两个参数 value 和 row 设置属性 height 给表格指定高度;数据 columns 的项设置 fixed 为 left 或 right,可以左右固定需要的列,设置属性 size 为 large 或 small 可以调整表格尺寸为大或小,默认不填或填写 default 为中 设置属性 stripe ,表格会间隔显示不同颜色 设置属性 border ,添加表格的边框线 通过设置属性 loading 可以让表格处于加载中状态,在异步请求数据、分页时建议使用 设置属性 highlight-row,可以选中某一行,调用 clearCurrentRow 方法可以手动清除选中项 自定义列模板使用 slot-scope 写法,在 columns 的某列声明 slot 后,就可以在 Table 的 slot 中使用 slot-scopeslot-scope 的参数有 3 个:当前行数据 row,当前列数据 column,当前行序号 index <table border :columns="columns2" :data="data2"> <template slot-scope="{ row, index }" slot="action"> <button type="primary" size="small" style="margin-right: 5px" @click="show(index)" > View </button> <button type="error" size="small" @click="remove(index)">Delete</button> </template></table><script> export default { data() { return { columns2: [ { title: 'Name', key: 'name' }, { title: 'Age', key: 'age' }, { title: 'Address', key: 'address' }, { title: 'Action', slot: 'action', width: 150, align: 'center' }, ], data2: [ { name: 'name2', age: 'age2', address: 'addr2' }, { name: 'name3', age: 'age3', address: 'addr3' }, ], } }, methods: { show(index) { this.$Modal.info({ title: 'User Info', content: `Name:${this.data2[index].name}<br>Age:${this.data2[index].age}<br>Address:${this.data2[index].address}`, }) }, remove(index) { this.data6.splice(index, 1) }, }, }</script> 表格 API 详解:https://www.iviewui.com/components/table#API Select<select v-model="model1" style="width:200px"> <option v-for="item in cityList" :value="item.value" :key="item.value"> {{ item.label }} </option></select><script> export default { data() { return { cityList: [ { value: 'New York', label: 'New York' }, { value: 'London', label: 'London' }, ], model1: '', } }, }</script> 通过设置 size 属性为 large 和 small 将输入框设置为大和小尺寸 Select 设置属性 disabled 禁用整个选择器: Option 设置属性 disabled 可以禁用当前项,clearable 可以清空已选项,multiple 可以开启多选模式 使用 OptionGroup 可将选项进行分组<OptionGroup label="Cities"> <Option ></Option></OptionGroup> Option 自定义模板 <option value="New York" label="New York"> <span>New York</span> <span style="float:right;color:#ccc">America</span></option> Slider<template> <Slider v-model="value1"></Slider> <Slider v-model="value2" :step="10"></Slider> <!--step 控制滑动间隔--> <Slider v-model="value3" range></Slider> <!--range 开启双滑块--> <Slider v-model="value3" range disabled></Slider> <!--disabled 禁用滑块--> <Slider v-model="value4" show-input></Slider> <!--show-input 显示数字输入框--></template> 使用 tip-format 可以自定义提示 <template> <Slider v-model="value5" :tip-format="format"></Slider></template><script> export default { data() { return { value5: 25 } }, methods: { format(val) { return 'Progress: ' + val + '%' }, }, }</script> Date/Time Picker1.DatePicker <template> <DatePicker type="date" placeholder="Select date" style="width: 200px" ></DatePicker> <DatePicker type="daterange" placement="bottom-end" placeholder="Select date" style="width: 200px" ></DatePicker></template> 设置属性 type 为 year 或 month 可以使用选择年或月的功能,date 或 daterange 分别显示选择单日和选择范围类型开启属性 multiple 后,可以多选,设置属性 format 可以改变日期的显示格式设置属性 confirm,选择日期后,选择器不会主动关闭,需用户确认后才可关闭 2.TimePicker <template> <TimePicker type="time" placeholder="Select time" style="width: 168px" ></TimePicker> <TimePicker type="timerange" placement="bottom-end" placeholder="Select time" style="width: 168px" ></TimePicker></template> 设置类似 DatePicker Cascader<template> <Cascader :data="data" v-model="value1"></Cascader></template><!--每项数据至少包含 value、label 两项,子集为 children--><script> export default { data() { return { value1: [], data: [ { value: 'data1', label: 'name1', children: [ { value: 'data1-1', label: 'name1-1' }, { value: 'data1-2', label: 'name1-2' }, { value: 'data1-3', label: 'name1-3' }, ], }, { value: 'data2', label: 'name2', children: [ { value: 'data2-1', label: 'name2-1' }, { value: 'data2-2', label: 'name2-2' }, ], }, ], } }, }</script> 指定 value 默认值,组件会在初始化时选定数据设置属性 trigger 为 hover,当鼠标悬停时就会展开子集设置属性 change-on-select 点任何一级都可以做到选择即改变使用属性 filterable 可直接搜索选项并选择 TransferInputNumberRateUploadColorPickerFormAutoComplete]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>iview</tag>
</tags>
</entry>
<entry>
<title><![CDATA[imblearn API]]></title>
<url>%2F2019%2F08%2F20%2Fimbalanced_data_analysis%2F</url>
<content type="text"><![CDATA[imblearn 是 python 的第三方库,用于处理不平衡数据(imbalanced data)的分类,一般分为降采样,过采样和综合采样 imblearn.under_sampling 降采样使用imblearn.under_sampling.prototype_generation来生成新样本 常用参数sampling_strategyreturn_indicesrandom_staten_neighborsn_seeds_Skind_seln_jobsratio 原型选择CondensedNearestNeighbour(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=None, n_seeds_S=1, n_jobs=1, ratio=None)基于压缩最近邻方法执行欠采样EditedNearestNeighbours(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=3, kind_sel='all', n_jobs=1, ratio=None)基于编辑的最近邻居方法执行欠采样RepeatedEditedNearestNeighbours(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=3, max_iter=100, kind_sel='all', n_jobs=1, ratio=None)基于重复编辑的最近邻居方法执行欠采样AllKNN(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=3, kind_sel='all', allow_minority=False, n_jobs=1, ratio=None)基于 AllKNN 方法执行欠采样InstanceHardnessThreshold(estimator=None, sampling_strategy='auto', return_indices=False, random_state=None, cv=5, n_jobs=1, ratio=None)根据实例硬度阈值执行欠采样NearMiss(sampling_strategy='auto', return_indices=False, random_state=None, version=1, n_neighbors=3, n_neighbors_ver3=3, n_jobs=1, ratio=None)基于 NearMiss 方法执行欠采样NeighbourhoodCleaningRule(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=3, kind_sel='all', threshold_cleaning=0.5, n_jobs=1, ratio=None)根据邻居清洁规则进行欠采样OneSidedSelection(sampling_strategy='auto', return_indices=False, random_state=None, n_neighbors=None, n_seeds_S=1, n_jobs=1, ratio=None)基于单侧选择方法执行欠采样RandomUnderSampler(sampling_strategy='auto', return_indices=False, random_state=None, replacement=False, ratio=None)[source]用于执行随机欠采样TomekLinks(sampling_strategy='auto', return_indices=False, random_state=None, n_jobs=1, ratio=None)通过删除 Tomek 的链接来执行欠采样 s imblearn.over_sampling 过采样ADASYN([sampling_strategy,…]) 使用自适应合成(ADASYN)采样方法对不平衡数据集执行过采样。BorderlineSMOTE([…]) 使用 Borderline SMOTE 进行过采样。KMeansSMOTE([…]) 在使用 SMOTE 进行过采样之前应用 KMeans 聚类。RandomOverSampler([…]) 用于执行随机过采样的类。SMOTE([sampling_strategy,…]) 使用 SMOTE 执行过采样的类。SMOTENC(categorical_features) 标称和连续的合成少数过采样技术(SMOTE-NC)。SVMSMOTE([sampling_strategy,…]) 使用 SVM-SMOTE 进行过采样。 imblearn.combine 组合采样SMOTEENN([sampling_strategy,…]) 使用 SMOTE 执行过采样并使用 ENN 进行清洁的类。SMOTETomek([sampling_strategy,…]) 使用 SMOTE 执行过采样并使用 Tomek 链接进行清洁的类。 imblearn.ensemble 方法整合BalancedBaggingClassifier([…]) Bagging 分级机,具 有额外的平衡功能。BalancedRandomForestClassifier([…]) 平衡的随机森林分类器。EasyEnsemble(** kwargs) 通过迭代应用随机欠采样来创建集合集。EasyEnsembleClassifier([…]) 一袋平衡的提升学习者也被称为 EasyEnsemble。RUSBoostClassifier([…]) 随机欠采样集成在 AdaBoost 分类器的学习中。 参考资料:https://imbalanced-learn.org/en/stable/index.htmlhttps://github.com/scikit-learn-contrib/imbalanced-learnhttps://blog.csdn.net/qq_31813549/article/details/79964973]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>python</tag>
</tags>
</entry>
<entry>
<title><![CDATA[iview_note 学习笔记(1)]]></title>
<url>%2F2019%2F08%2F16%2Fiview-note%2F</url>
<content type="text"><![CDATA[iview 前端 UI 学习笔记和组件范例收集,iview 框架适合桌面端的页面设计,拥有比较全面的动态组件。详细使用参考官网:https://www.iviewui.com/components/ iview_note 学习笔记(2)iview_note 学习笔记(3) 安装建立 vue-cli,之后通过 vue 建立项目文件夹 npm install -g @vue/clivue create new-project 或者直接 vue uinpm install [email protected] --save 或直接在vue cli界面中安装plugin 或者在页面下直接进行导入 <!-- import Vue.js --><script src="//vuejs.org/js/vue.min.js"></script><!-- import stylesheet --><link rel="stylesheet" href="//unpkg.com/iview/dist/styles/iview.css" /><!-- import iView --><script src="//unpkg.com/iview/dist/iview.min.js"></script> 引入 iviewimport './plugins/iview.js'import 'iview/dist/styles/iview.css' 在文件 .babelrc 中配置可实现按需求引用 // .babelrc{ "plugins": [["import", { "libraryName": "iview", "libraryDirectory": "src/components" }]]} 然后这样按需引入组件,就可以减小体积了: import { Button, Table } from 'iview'Vue.component('Button', Button)Vue.component('Table', Table) 使用规则在非 template/render 模式下(例如使用 CDN 引用时),组件名要分隔,例如 DatePicker 必须要写成 date-picker。 以下组件,在非 template/render 模式下,需要加前缀 i-: Button: i-buttonCol: i-colTable: i-tableInput: i-inputForm: i-formMenu: i-menuSelect: i-selectOption: i-optionProgress: i-progressTime: i-time 以下组件,在所有模式下,必须加前缀 i-,除非使用 iview-loader: Switch: i-switchCircle: i-circle iview-loader 用于统一 View UI(iView) 标签书写规范,所有标签都可以使用首字母大写的形式,包括 Vue 限制的两个标签 Switch 和 Circle 基础组件View UI(iView) 使用较为安全的蓝色作为主色调 辅助色: Info #2db7f5;Success #19be6b;Warning #ff9900;Error #ed4014 中性色: 标题 #17233d;正文 #515a6e;辅助/图标 #808695;失效 #c5c8ce;边框 #dcdee2;分割线 #e8eaec;背景 #f8f8f9 字体: font-family: “Helvetica Neue”,Helvetica,”PingFang SC”,”Hiragino Sans GB”,”Microsoft YaHei”,”微软雅黑”,Arial,sans-serif; button 样式: <template> <Button>Default</Button> <Button type="primary">Primary</Button> <Button type="dashed">Dashed</Button> <Button type="text">Text</Button> <Button type="info">Info</Button> <Button type="success">Success</Button> <Button type="warning">Warning</Button> <Button type="error">Error</Button></template><script> export default { }</script> 设置内容反色和背景透明可以加入属性 ghost设置查询 icon 可以在 button 中内嵌图标,可以设置形状 <Button type="primary" shape="circle" icon="ios-search">通过设置 size 为 large 和 small 将按钮设置为大和小尺寸通过设置属性 long 可将按钮宽度设置为 100%通过添加 disabled 属性可将按钮设置为不可用状态通过添加 loading 属性可以让按钮处于加载中状态通过设置 ButtonGroup 的属性 vertical,可以使按钮组纵向排列通过设置 to 可以实现点击按钮直接跳转,支持传入 vue-router 对象将多个 Button 放入 ButtonGroup 内,可实现按钮组合的效果 Icon: View UI(iView) 的图标使用开源项目 ionicons 3.x 版本 可设置图标的名称,大小,颜色或者自定义图标 图标使用可搜索官方文档 导航组件Menu<template> <menu mode="horizontal" :theme="theme1" active-name="1"> <menuitem name="1"> 内容1 </menuitem> <menuitem name="2"> 内容2 </menuitem> <Submenu name="3"> <template slot="title"> 内容3 </template> <MenuGroup title="子标题"> <menuitem name="3-1">子内容1</menuitem> <menuitem name="3-2">子内容2</menuitem> <menuitem name="3-3">子内容3</menuitem> </MenuGroup> </Submenu> </menu></template> <Menu>:mode 可选值为 horizontal(水平) 和 vertical(垂直)theme 主题,可选值为 light、dark、primaryactive-name 激活菜单的 name 值open-names 展开的 Submenu 的 name 集合accordion 是否开启手风琴模式,开启后每次至多展开一个子菜单 <MenuItem>:需要写唯一标识 name可使用 to 进行跳转链接 <Submenu>:设置子菜单,需要写唯一标识 name<MenuGroup>:可以对标题进行分组 Tabs<template> <Tabs value="name1"> <TabPane label="标签一" name="name1">标签一的内容</TabPane> <TabPane label="标签二" name="name2">标签二的内容</TabPane> <TabPane label="标签三" name="name3">标签三的内容</TabPane> </Tabs></template> <Tabs>:type 设置页签的基本样式,可选值为 line 和 cardsize 设置尺寸,可选值为 default 和 small,仅在 type=”line” 时有效Tabs 中的 value 设置当前激活的 TabPane <TabPane>:name 用于标识当前面板,对应 value,默认为其索引值可设置属性 icon,可以显示一个图标可使用 disabled 禁用选项卡closable 设置是否可以关闭页签 Dropdown<template> <Dropdown style="margin-left: 20px"> <button type="primary"> 下拉菜单 <Icon type="ios-arrow-down"></Icon> </button> <DropdownMenu slot="list"> <DropdownItem>目录1</DropdownItem> <DropdownItem disabled>目录2</DropdownItem> <DropdownItem divided>目录3</DropdownItem> </DropdownMenu> </Dropdown></template> <Dropdown>:trigger 触发方式可选值为 hover(悬停)click(点击)contextMenu(右键)custom(自定义)设置属性 placement 可以更改下拉菜单出现的方向,可选值为 top top-start top-end bottom bottom-start bottom-end left left-start left-end righ tright-start right-end <DropdownItem>:disabled 设置禁用该项divided 显示分割线selected 标记该项为选中状态 Page<Page :total="100" /> <Page :total="100" show-sizer /><!--切换每页显示的数量--><Page :total="100" show-elevator /><!--快速跳转到某一页--><Page :total="100" show-total /><!--显示总共多少条数据--><Page :total="40" size="small" /><!--设置size为small使用迷你型--><Page :current="2" :total="50" simple /><!--设置simple属性即可使用简洁版的分页--><Page :total="100" prev-text="Previous" next-text="Next" /><!--使用属性 prev-text 和 next-text,替代图标显示为文字--> Breadcrumb面包屑组件,可以作为字导航菜单使用,小巧精简。 <Breadcrumb> <BreadcrumbItem to="/"> <Icon type="ios-home-outline"></Icon> Home </BreadcrumbItem> <BreadcrumbItem>Components</BreadcrumbItem></Breadcrumb> Steps<template> <Steps :current="1"> <!--组件会根据current自动判断各步骤状态--> <Step title="已完成" content="这里是该步骤的描述信息"></Step> <Step title="进行中" content="这里是该步骤的描述信息"></Step> <Step title="待进行" content="这里是该步骤的描述信息"></Step> <Step title="待进行" content="这里是该步骤的描述信息"></Step> </Steps></template> 设置属性 direction 为 vertical 在垂直方向展示设置 Steps 的属性 status 为 error 指定当前错误步骤状态设置属性 size 为 small 启用迷你版通过设置 Step 的 icon 属性可以自定义图标 Anchor可以作为目录使用 <Anchor show-ink> <AnchorLink href="#basic_usage" title="Basic Usage" /> <AnchorLink href="#static_position" title="Static Position" /> <AnchorLink href="#API" title="API"> <AnchorLink href="#Anchor_props" title="Anchor props" /> <AnchorLink href="#Anchor_events" title="Anchor events" /> <AnchorLink href="#AnchorLink_props" title="AnchorLink props" /> </AnchorLink></Anchor>]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>iview</tag>
</tags>
</entry>
<entry>
<title><![CDATA[tip:决策树、随机森林结果可视化]]></title>
<url>%2F2019%2F08%2F10%2Fdecision-tree-visualization%2F</url>
<content type="text"><![CDATA[scikit-learn 决策树结果的可视化,方便观察模型,以及发现模型中的问题。需要安装 graphviz 环境搭建安装 graphvizlinux:sudo apt install graphvizwindows: 去官网下载 http://www.graphviz.org/ 设置环境变量:将 graphviz 的 bin 目录加到 PATH 安装 python 库 graphviz,pydotplus:pip install graphviz, pydotplus 可视化模型clf = DecisionTreeClassifier(max_depth=max_depth_val)clf.fit(X_train, y_train)# 使用graphviz提取出节点数据dot_data = tree.export_graphviz(clf, out_file=None, feature_names=feature_names, class_names=target_names, filled=True, rounded=True, special_characters=True) 生成可视化文件可利用 pydotplus 生成 pdf 文件 graph = pydotplus.graph_from_dot_data(dot_data)graph.write_pdf("dataset.pdf") 也可以利用 Ipython 的图片显示功能 from IPython.display import Imagegraph = pydotplus.graph_from_dot_data(dot_data)Image(graph.create_png()) 参考资料:https://blog.csdn.net/ydyang1126/article/details/78842952https://github.com/ljpzzz/machinelearning/blob/master/classic-machine-learning/decision_tree_classifier.ipynb]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>sklearn</tag>
</tags>
</entry>
<entry>
<title><![CDATA[如何写日志]]></title>
<url>%2F2019%2F08%2F04%2Fwrite_log%2F</url>
<content type="text"><![CDATA[在开发时学习书写日志的方法,方便做测试。例举使用 python 和 java 上的日志记录—loading…— 常用日志框架log4j、Logging、commons-logging、slf4j、logback Logging:Java 自带的日志工具类Log4j:Apache 的一个开源日志框架,log4j 在 2015/08/05 这一天被 Apache 宣布停止维护了,用户需要切换到 Log4j2 上面去commons-logging:日志的门面接口,它也是 apache 最早提供的日志门面接口,用户可以根据喜好选择不同的日志实现框架,而不必改动日志定义Slf4j:Simple Logging Facade for Java,即简单日志门面接口Logback:Slf4j 的原生实现框架,同样也是出自 Log4j 一个人之手,但拥有比 log4j 更多的优点、特性和更做强的性能,现在基本都用来代替 log4j 成为主流 commons-loggin、slf4j 只是一种日志抽象门面,不是具体的日志框架。 log4j、logback 是具体的日志实现框架。 推荐使用 slf4j + logback 还有slf4j + log4j commons-logging + log4j 这两种日志组合框架。 Python 的 logging 模块提供了通用的日志系统。logging 模块与 log4j 的机制相同,只是具体的实现细节不同。 日志级别 日志级别(Java) 描述 OFF 关闭:最高级别,不输出日志。 FATAL 致命:输出非常严重的可能会导致应用程序终止的错误。 ERROR 错误:输出错误,但应用还能继续运行。 WARN 警告:输出可能潜在的危险状况。 INFO 信息:输出应用运行过程的详细信息。 DEBUG 调试:输出更细致的对调试应用有用的信息。 TRACE 跟踪:输出更细致的程序运行轨迹。 ALL 所有:输出所有级别信息。 Java:ALL < TRACE < DEBUG < INFO < WARN < ERROR < FATAL < OFFPython:NOTSET < DEBUG < INFO < WARNING < ERROR < CRITICAL Log4J 的运用Log4j 有三个主要的组件:Loggers(记录器),Appenders(输出源)和 Layouts(布局),这里可简单理解为日志类别,日志要输出的地方和日志以何种形式输出 logging 的运用logging 模块提供 logger、handler、filter、formatter logger记录获取到的数据,通过模块的 getLogger(name)函数获得 logger = logging.getLogger('test') # 获取名为 test 的 loggerlogger.addHandler(handler) # 为 logger 添加 handlerlogger.setLevel(logging.DEBUG) 方法名 作用 setLevel(lvl) 设置日志级别 isEnabledFor(lvl) 检查某级别的日志是否启用 getEffectiveLevel() 获取实际的日志级别 debug/warning/info/error(msg, *args, **kwargs) 输出对应级别的日志 log(lvl, msg, *args, **kwargs) 输出指定级别的日志 addFilter(filt)/removeFilter(filt) 添加或删除指定的过滤器 addHandler(hdlr)/removeHandler(hdlr) 添加或删除指定的处理器 handler用于指定日志向哪里输出(文件、终端等等) 常用的 Handler 有以下几种: StreamHandler, 用于向标准输入输出流等输出日志。 FileHandler,用于向文件输出日志。 NullHandler,什么也不输出。 RotatingFileHandler,向文件输出日志,如果文件到达指定大小,创建新文件并继续输出日志。 相关 handler 类型参考python 官方文档 handler = logging.handlers.RotatingFileHandler(LOG_FILE,axBytes=1024*1024, backupCount = 5) # 实例化 handler formatter指定日志记录输出的具体格式,采用的是 %(key)s 的形式formatter 构造方法需要两个参数:消息的格式字符串和日期字符串 日志格式 含义 %(name)s 生成日志的 Logger 名称 %(levelno)s 数字形式的日志级别,包括 DEBUG, INFO, WARNING, ERROR 和 CRITICAL %(levelname)s 文本形式的日志级别,包括’DEBUG’、 ‘INFO’、 ‘WARNING’、 ‘ERROR’ 和’CRITICAL’ %(pathname)s 输出该日志的语句所在源文件的完整路径(如果可用) %(filename)s 文件名 %(module)s 输出该日志的语句所在的模块名 %(funcName)s 调用日志输出函数的函数名 %(lineno)d 调用日志输出函数的语句所在的代码行(如果可用) %(created)f 日志被创建的时间,UNIX 标准时间格式,表示从 1970-1-1 00:00:00 UTC 计算起的秒数 %(relativeCreated)d 日志被创建时间与日志模块被加载时间的时间差,单位为毫秒 %(asctime)s 日志创建时间。默认格式是 “2003-07-08 16:49:45,896”,逗号后为毫秒数 %(msecs)d 毫秒级别的日志创建时间 %(thread)d 线程 ID(如果可用) %(threadName)s 线程名称(如果可用) %(process)d 进程 ID(如果可用) %(message)s 日志信息 # 日志样例2019-08-04 23:21:59,682 - log_test.py:16 - test - first info message2019-08-04 23:21:59,682 - log_test.py:17 - test - first debug message# 日志格式%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s filter提供更细粒度的日志过滤功能,用于决定哪些日志记录将会被输出 config 模块配置日志logging.basicConfig()logging python 日志示例import loggingimport logging.handlersLOG_FILE = 'test.log'# 创建loggerlogger = logging.getLogger('test')logger.setLevel(logging.DEBUG)# 实例化handlerconsoleHandler = logging.StreamHandler()Filehandler = logging.handlers.RotatingFileHandler(LOG_FILE,axBytes = 1024*1024, backupCount = 5)# 实例化formatterfmt = '%(asctime)s - %(filename)s:%(lineno)s - %(name)s - %(message)s'formatter = logging.Formatter(fmt)# 为 handler 添加 formatterconsoleHandler.setFormatter(formatter)Filehandler。setFormatter(formatter)# 添加到logger中logger.addHandler(consolehandler)logger.addHandler(Filehandler)# 打印日志logger.info('info message')logger.debug('debug message')logger.warning('warn message')logger.error('error message')logger.critical('critical meaasge')logger.debug('%s 自定义信息' % 'define message') 参考资料:https://blog.csdn.net/wud_jiyanhui/article/details/6213443https://blog.csdn.net/u011054333/article/details/69215660https://help.aliyun.com/document_detail/28990.html?spm=a2c4g.11186623.6.746.7cfa66d8dwy2XOhttps://help.aliyun.com/document_detail/28989.html?spm=a2c4g.11186623.6.745.3ef949faCiQ7PW]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>python</tag>
<tag>log</tag>
</tags>
</entry>
<entry>
<title><![CDATA[boosting]]></title>
<url>%2F2019%2F08%2F01%2Fboosting%2F</url>
<content type="text"><![CDATA[XgBoost 和 LightGBM 官方文档阅读和算法学习*号为未解释完全,具体使用方法请参考官方文档 XgBoost常用参数booster [default= gbtree ] 基础模型类型,可选参数包括: gbtree、gblinear、dart,其中 gbtree、dart 为树模型、gblinear 为线性函数模型 eta 学习率 tree_method XGBoost 中树的构造算法,可选项包括: auto, exact, approx, hist, gpu_exact, gpu_hist eval_metric 依据目标函数选择评估指标rmse: 根均方误差mae: 平均绝对值误差logloss: 负的似然函数error: 二分类问题的分类错误率merror: 多分类问题的分类错误率mlogloss: 多分类问题的负似然函数auc: IOC 曲线下面积aucpr: PR 曲线下面积 updater 线性模型的拟合算法shotgun: 基于 shotgun 算法的坐标下降法coord_descent: 普通的坐标下降法feature_selector: 特征选择和排序算法 objective 训练的模型类型和目标函数reg:linear: 线性回归reg:logistic: 逻辑回归binary:logistic: 二分类问题, 输出概率值binary:logitraw: 二分类问题, 输出得分值,需要通过 sigmoid 函数转化成概率值binary:hinge: 二分类问题,使用铰链损失函数,输出 0 或 1,而不是概率值count:poisson: 用于计数问题的泊松分布,输出泊松分布的均值。survival:cox: Cox regression for right censored survival time datamulti:softmax: 多分类目标函数, 使用此目标函数,需要设置样本类别数据: num_classmulti:softprob: 同 softmax, 但是输出的结果为 ndata * nclass 维的向量,表示样本属于每个类别的概率 cyclic: 循环变量特征shuffle: 类型与循环变量特征,但是在每次更新时都会随机打乱特征的顺序random: 随机(带替换)的坐标选择器greedy: 选择最大梯度的坐标thrifty: 近似 greedy 的坐标选择器top_k: greedy 算法和 thrifty 算法选择的最优特征数量,0 表示不限制。 API1. 数据结构类,提供数据的构建和处理xgboost.DMatrix(data, label=None, missing=None, weight=None, silent=False, feature_names=None, feature_types=None) data数据源或文件路径label训练数据的标签missing缺省值表示字符,如果没填, 默认值为:np.nanweight每个样本的权重silent构造数据结构时是否显示日志feature_names各个特征的名称feature_types各个特征的数据类型nthread 加载数据开启的线程数 2. 模型类,提供了一些基础的函数,如模型加载、保存、评估和预测等方法xgboost.Booster(params=None, cache=(), model_file=None) load_model(fname)从文件或内存中加载模型,参数含义如下:fname (string or a memory buffer) – 模型文件名称或内存缓存对象2. save_model(fname)将模型保存到文件中,参数的含义如下:fname (string) – 输出文件的名称3. eval(data, name, iteration)用给定的数据评估模型好坏,参数的含义如下:data (DMatrix) – 用于评估模型的数据name (str, 可选) – 用于评估模型的数据集名称iteration (int, 可选) –迭代次数 3. 对模型进行训练xgboost.train(params, dtrain, num_boost_round=10, evals=(), obj=None, feval=None, maximize=False, early_stopping_rounds=None, evals_result=None, verbose_eval=True, learning_rates=None, xgb_model=None, callbacks=None) params配置参数dtrain训练数据num_boost_round生成树的数量evals评估数据obj自定义的目标函数feval自定义的评价函数maximize是否最大化评价指标early_stopping_rounds错误率 early_stopping_rounds 轮未下降,则停止训练evals_result模型评估结果learning_rates学习率xgb_model在训练前加载之前训练的模型callback设置回调函数,比如重新设置学习率 4. 对数据分类xgboost.XGBClassifier(max_depth=3, learning_rate=0.1, n_estimators=100, silent=True, objective='binary:logistic', nthread=-1, gamma=0, min_child_weight=1, max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, base_score=0.5, seed=0, missing=None) max_depth 最大树深度learning_rate 学习率n_estimators 树的迭代次数gamma 节点分裂需要下降的最小损失min_child_weight 节点中样本的最小权重和max_delta_step 每轮允许叶子输出值的最大增量subsample 每轮训练使用的样本数量等于样本总数乘以采样率colsample_bytree 每轮训练使用的特征占比colsample_bylevel 每层训练使用的特征占比reg_alpha L1 正则reg_lambda L2 正则scale_pos_weight 用于控制正例和负例均衡的权重base_score 初始时各个样本的得分 5. 数据拟合和预测 xgboost.fit(X, y, sample_weight=None, eval_set=None, eval_metric=None, early_stopping_rounds=None, verbose=True)# sample_weight:每个训练样本的权重# eval_set:设置验证集# eval_metric:验证的度量指标# early_stopping_rounds` 指定连续多少轮未改善后停止xgboost.predict(data, output_margin=False, ntree_limit=0, pred_leaf=False, pred_contribs=False, approx_contribs=Flase, pred_interactions=False, validate_features=Flase)`# output_margin 是否输出原始未经转化的值# ntree_limit 用于预测的树的数量,默认为0,代表使用所有树进行预测# pred_leaf 指明每条数据分别落到每棵树的哪个叶子节点上# pred_contribs 指明每个样本的每个特征对预测结果的贡献值# approx_contribs 是否启用特征贡献大小的预估功能# pred_interactions 指明两两特征间相互影响的SHAP值# validate_features首先验证待预测的数据特征名称是否与模型中的特征名称相同,默认情况下,系统认为他们是相同的,不进行验证 class xgboost.XGBRegressor()用于回归任务 XgBoost 示例import xgboost as xgbimport pandas as pdfrom sklearn.model_selection import train_test_splitfrom sklearn.metrics import roc_auc_scoretrain_data = pd.read_csv('train.csv') # 读取数据y = train_data.pop('30').values # 用pop方式将训练数据中的标签值y取出来,作为训练目标,这里的‘30’是标签的列名col = train_data.columnsx = train_data[col].values # 剩下的列作为训练数据train_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.333, random_state=0) # 分训练集和验证集# 这里不需要Dmatrixparameters = { 'max_depth': [5, 10, 15, 20, 25], 'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15], 'n_estimators': [500, 1000, 2000, 3000, 5000], 'min_child_weight': [0, 2, 5, 10, 20], 'max_delta_step': [0, 0.2, 0.6, 1, 2], 'subsample': [0.6, 0.7, 0.8, 0.85, 0.95], 'colsample_bytree': [0.5, 0.6, 0.7, 0.8, 0.9], 'reg_alpha': [0, 0.25, 0.5, 0.75, 1], 'reg_lambda': [0.2, 0.4, 0.6, 0.8, 1], 'scale_pos_weight': [0.2, 0.4, 0.6, 0.8, 1]}xlf = xgb.XGBClassifier(max_depth=10, learning_rate=0.01, n_estimators=2000, silent=True, objective='binary:logistic', nthread=-1, gamma=0, min_child_weight=1, max_delta_step=0, subsample=0.85, colsample_bytree=0.7, colsample_bylevel=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, seed=1440, missing=None)# 有了gridsearch我们便不需要fit函数gsearch = GridSearchCV(xlf, param_grid=parameters, scoring='accuracy', cv=3)gsearch.fit(train_x, train_y)print("Best score: %0.3f" % gsearch.best_score_)print("Best parameters set:")best_parameters = gsearch.best_estimator_.get_params()for param_name in sorted(parameters.keys()): print("\t%s: %r" % (param_name, best_parameters[param_name])) LightGBMparamenter 常用参数objective:‘regression’,’regression_l2’,’mean_squared_error’,’mse’,’l2_root’,’root_mean_squred_error’,’rmse’: 表示回归任务,但是使用 L2 损失函数。默认为’regression’‘binary’: 表示二分类任务,使用对数损失函数作为目标函数。‘multiclass’: 表示多分类任务,使用 softmax 函数作为目标函数。必须设置 num_class 参数‘multiclassova’,’multiclass_ova’,’ova’,’ovr’: 表示多分类任务,使用 one-vs-all 的二分类目标函数。必须设置 num_class 参数‘regression_l1’,’mae’,’mean_absolute_error’: 表示回归任务,但是使用 L1 损失函数。‘huber’: 表示回归任务,但是使用 huber 损失函数。‘fair’: 表示回归任务,但是使用 fair 损失函数。‘poisson’: 表示 Poisson 回归任务。‘quantile’: 表示 quantile 回归任务。‘quantile_l2’:表示 quantile 回归任务,但是使用了 L2 损失函数。‘mape’,’mean_absolute_precentage_error’: 表示回归任务,但是使用 MAPE 损失函数‘gamma’: 表示 gamma 回归任务。‘tweedie’: 表示 tweedie 回归任务。‘xentropy’,’cross_entropy’: 目标函数为交叉熵(同时具有可选择的线性权重)。要求标签是[0,1] 之间的数值。‘xentlambda’,’cross_entropy_lambda’: 替代了参数化的 cross_entropy 。要求标签是[0,1] 之间的数值。‘lambdarank’:表示排序任务。 boosting_type: // 基学习器模型算法‘gbdt’: 表示传统的梯度提升决策树。默认值为’gbdt’‘rf’: 表示随机森林。‘dart’: 表示带 dropout 的 gbdt‘goss’:表示 Gradient-based One-Side Sampling 的 gbdt metric://指定度量的指标‘l1’ 或者 mean_absolute_error 或者 mae 或者 regression_l1: 表示绝对值损失‘l2’ 或者 mean_squared_error 或者 mse 或者 regression_l2 或者 regression:表示平方损失‘l2_root’ 或者 root_mean_squared_error 或者 rmse:表示开方损失‘quantile’ 表示 Quantile 回归中的损失‘mape’ 或者 ‘mean_absolute_percentage_error’ 表示 MAPE 损失‘huber’ 表示 huber 损失‘fair’ 表示 fair 损失‘poisson’ 表示 poisson 回归的负对数似然‘gamma’ 表示 gamma 回归的负对数似然‘gamma_deviance’ 表示 gamma 回归的残差的方差‘tweedie’ 表示 Tweedie 回归的负对数似然‘ndcg’ 表示 NDCG‘map’ 或者’mean_average_precision’ 表示平均的精度‘auc’ 表示 AUC‘binary_logloss’或者’binary’ 表示二类分类中的对数损失函数‘binary_error’ 表示二类分类中的分类错误率‘multi_logloss’或者 ‘multiclass’或者 ‘softmax’或者 ‘multiclassova’或者 ‘multiclass_ova’,或者’ova’或者 ‘ovr’ 表示多类分类中的对数损失函数‘multi_error’ 表示多分类中的分类错误率‘xentropy’或者’cross_entropy’ 表示交叉熵‘xentlambda’ 或者’cross_entropy_lambda’ 表示 intensity 加权的交叉熵‘kldiv’或者’kullback_leibler’ 表示 KL 散度 数据结构1. 数据结构类,提供数据的构建和处理lightgbm.Dataset(data, label=None, max_bin=None, reference=None, weight=None, group=None, init_score=None, silent=False, feature_name='auto', categorical_feature='auto', params=None, free_raw_data=True) label 指定数据的标签列max_bin 特征值最大分类数量reference 增加评估参照,评估模型时使用,reference=trainweight 设置权重group 设置数据组的大小init_score 加入之前的分数silent 是否在训练过程中屏蔽输出feature_name 特征名字categorical_feature设置分类特征free_raw_data 创建完后释放数据 2. 模型类,提供了一些基础的函数,如模型加载、保存、评估和预测等方法lightgbm.Booster(params=None, train_set=None, model_file=None, model_str=None, silent=False)params 一个字典或者 None,给出了 Booster 的参数。默认为 Nonetrain_set 一个 Dataset 对象或者 None,给出了训练集。 默认为 Nonemodel_file 一个字符串或者 None,给出了 model file 的路径。 默认为 Nonesilent 一个布尔值,指示是否在构建过程中打印消息。默认为 False lightgbm.add_valid(data,name) # 添加一个验证集。lightgbm.current_iteration() # 返回当前的迭代的index(即迭代的编号)lightgbm.dump_model(num_iteration=-1) # dump 当前的Booster 对象为json 格式。lightgbm.eval(data,name,feval=None) # 对指定的数据集evaluatelightgbm.eval_train(feval=None) # 对训练集进行evaluatelightgbm.eval_valid(feval=None) # 对验证集进行evaluatelightgbm.feature_importance(importance_type='split', iteration=-1) # 获取特征的importancelightgbm.feature_name() # 获取每个特征的名字。lightgbm.free_dataset() # 释放Booster 对象的数据集lightgbm.free_network() # 释放Booster 对象的Networklightgbm.get_leaf_output(tree_id, leaf_id) # 获取指定叶子的输出lightgbm.num_feature() # 获取特征的数量(即由多少列特征)lightgbm.reset_parameter(params) #重设Booster 的参数。lightgbm.rollback_one_iter() # 将Booster 回滚一个迭代步lightgbm.save_model(filename,num_iteration=-1) # 保存Booster 对象到文件中。lightgbm.set_attr(**kwargs) # 设置Booster 的属性。lightgbm.set_network(machines,local_listen_port=12400,listen_time_out=120,num_machines=1) # 配置网络lightgbm.set_train_data_name(name) # 设置训练集的名字lightgbm.update(train_set=None, fobj=None) # 更新一个迭代步 训练1. lightgbm.train()执行训练 lightgbm.train(params, train_set, num_boost_round=100, valid_sets=None, valid_names=None, fobj=None, feval=None, init_model=None, feature_name='auto', categorical_feature='auto', early_stopping_rounds=None, evals_result=None, verbose_eval=True, learning_rates=None, keep_training_booster=False, callbacks=None) params 相关参数配置,另外导入字典train_set 训练数据num_boost_round boost 迭代次数valid_sets,valid_names 设置训练时用于评估的数据集 fobj 自定义目标函数 preds, train_data -> grad,hess feval 自定义评估函数 preds, traindata -> eval_name, eval_result, is_higher_better init_model 导入之前训练数据feature_name 指定特征名字,数据源为 pandas DataFrame 会使用里面的 columnnamescategorical_feature 指定分类特征early_stopping_rounds 指定连续多少轮未改善后停止evals_result 指定字典存储 valid_sets 中验证的结果 verbose_eval 设置打印评估的间隔,可设置每个提升阶段打印或间隔verbose_eval个阶段打印learning_rates 设置学习率keep_training_booster 设置训练得到的 booster 是否继续训练callbacks 设置每次迭代后需要执行的函数 最后返回 booster 实例 2. lightgbm.cv() 执行交叉检验 lightgbm.cv(params, train_set, num_boost_round=10, folds=None, nfold=5, stratified=True, shuffle=True, metrics=None, fobj=None, feval=None, init_model=None, feature_name='auto',categorical_feature='auto', early_stopping_rounds=None, fpreproc=None, verbose_eval=None, show_stdv=True, seed=0, callbacks=None) folds:一个生成器、一个迭代器、或者 None nfold:指定交叉检验的数量。默认为 5stratified:指示是否进行分层拆分shuffle:指示是否在拆分之前先混洗数据metrics:指定评估度量标准,在 params 中设置fpreproc:设置预处理函数,在训练开始之前进行 show_stdv:在训练过程中展示标准差信息seed:一个整数,给出了生成 fold 的随机数种子 * 最后以字典的形式返回检验结果的均值和标准差 scikit-learn API1. LGBMMOdel实现 lightgbm 在 scikir-learn 中的接口,详见分类和回归任务 2. LGBMClassifier: LGBMModel 的子类,用于分类任务 lightgbm.LGBMClassifier(boosting_type='gbdt', num_leaves=31, max_depth=-1, learning_rate=0.1, n_estimators=10, max_bin=255, ubsample_for_bin=200000, objective=None, min_split_gain=0.0, in_child_weight=0.001, min_child_samples=20, subsample=1.0, subsample_freq=1, colsample_bytree=1.0, reg_alpha=0.0, reg_lambda=0.0, random_state=None, n_jobs=-1, silent=True, **kwargs) boosting_type: 指定学习器的算法’gbdt, rf, dart, goss’num_leaves:一棵树上的叶子数max_depth:树模型的最大深度learning_rate:学习率n_estimators:提升树的数量max_bin: 每个特征的最大分支数量class_weight:给出了每个类别的权重占比subsample_for_bin:构建直方图的样本的数量 objective:问题类型以及对应的目标函数,对于 LGBMRegressor 为’regression’;对于 LGBMClassifier 为’binary’ 或者’multiclass’;对于 LGBMRanker 为’lambdarank’min_split_gain:执行切分的最小增益min_child_weight:一个叶子节点上的最小权重之和,默认为 1e-3min_child_samples: 一个叶子节点上包含的最少样本数量subsample: 表示训练样本的采样比例,取值范围为[0.0,1.0]。如果小于 1.0,则 lightgbm 会在每次迭代中随机选择部分样本来训练(非重复采样)subsample_freq:表示训练样本的采样频率colsample_bytree:表示特征的采样比例,取值范围为[0.0,1.0]。如果小于 1.0,则 lightgbm 会在每次迭代中随机选择部分特征reg_alpha:L1 正则化系数reg_lambda:L2 正则化系数random_state:随机数种子 n_jobs:并行线程数量silent:是否在训练过程中屏蔽输出 import lightgbm as lgbgbm = lgb.LGBMClassifier()gbm.n_features_:# 给出了特征的数量gbm.classes_:# 样本的标签gbm.n_classes_:# 类别的数量gbm.best_score_:# 训练完毕模型的最好的scoregbm.best_iteration_:# 训练完毕模型的最好的迭代数gbm.objective_:# 训练模型的目标函数gbm.booster_:# 底层的Booster 对象gbm.evals_result_:# 模型评估结果gbm.feature_importances_: # 特征的重要性 预测gbm.fit(X, y, sample_weight=None, init_score=None, eval_set=None, eval_names=None, eval_sample_weight=None, eval_init_score=None, eval_metric='logloss', early_stopping_rounds=None, verbose=True, feature_name='auto', categorical_feature='auto', callbacks=None)`# sample_weight:每个训练样本的权重# init_score:每个训练样本的初始分数# group:每个训练样本的分组# eval_set:设置验证集# eval_names:设置验证集的名字# eval_sample_weight:验证集中每个样本的权重# eval_init_score:每个验证集中,每个样本的init score# eval_group:每个验证集中,每个样本的分组# eval_metric:验证的方法gbm.predict(data, num_iteration=-1, raw_score=False, pred_leaf=False, pred_contrib=False, data_has_header=False, is_reshape=True, pred_parameter=None)# num_iteration`:设置在预测时,使用多少个子树# raw_score`:是否输出raw score# pred_leaf: 输出每个样本在每个子树的哪个叶子上# pred_contrib:输出每个特征对每个样本预测结果的贡献程度# data_has_header:指示数据集是否含有标题# is_reshape:是否reshape# pred_parameter:给出其它的参数gbm.predict_proba(X, raw_score=False, num_iteration=0) LGBMRegressor 是 LGBMModel 的子类,它用于回归任务 LGBMRanker 是 LGBMModel 的子类,它用于排序任务,详见排序学习算法 绘图 APIbooster APILightGBM 示例import pandas as pdimport lightgbm as lgbfrom sklearn.grid_search import GridSearchCV # Perforing grid searchfrom sklearn.model_selection import train_test_splittrain_data = pd.read_csv('train.csv') # 读取数据y = train_data.pop('30').values # 用pop方式将训练数据中的标签值y取出来,作为训练目标,这里的‘30’是标签的列名col = train_data.columnsx = train_data[col].values # 剩下的列作为训练数据train_x, valid_x, train_y, valid_y = train_test_split(x, y, test_size=0.333, random_state=0) # 分训练集和验证集train = lgb.Dataset(train_x, train_y)valid = lgb.Dataset(valid_x, valid_y, reference=train)parameters = { 'max_depth': [15, 20, 25, 30, 35], 'learning_rate': [0.01, 0.02, 0.05, 0.1, 0.15], 'feature_fraction': [0.6, 0.7, 0.8, 0.9, 0.95], 'bagging_fraction': [0.6, 0.7, 0.8, 0.9, 0.95], 'bagging_freq': [2, 4, 5, 6, 8], 'reg_alpha': [0, 0.1, 0.4, 0.5, 0.6], 'reg_lambda': [0, 10, 15, 35, 40], 'cat_smooth': [1, 10, 15, 20, 35]}gbm = lgb.LGBMClassifier(boosting_type='gbdt', objective = 'binary', metric = 'auc', verbose = 0, learning_rate = 0.01, num_leaves = 35, feature_fraction=0.8, bagging_fraction= 0.9, bagging_freq= 8, reg_alpha= 0.6, reg_lambda= 0)gsearch = GridSearchCV(gbm, param_grid=parameters, scoring='accuracy', cv=3)gsearch.fit(train_x, train_y)print("Best score: %0.3f" % gsearch.best_score_)print("Best parameters set:")best_parameters = gsearch.best_estimator_.get_params()for param_name in sorted(parameters.keys()): print("\t%s: %r" % (param_name, best_parameters[param_name]))]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>boosting</tag>
</tags>
</entry>
<entry>
<title><![CDATA[scikit-learn 文档学习笔记(1)]]></title>
<url>%2F2019%2F07%2F30%2Fscikit-learn-note%2F</url>
<content type="text"><![CDATA[—loading …—scikit-learn 基于 Python 语言,建立在 NumPy ,SciPy 和 matplotlib 上,是简单高效的数据挖掘和数据分析工具文章记录 scikit-learn API 的使用方法,包括监督学习、无监督学习,模型的选择和评估,数据集的加载和转换学习笔记(1) 为监督学习的内容,解决回归和分类问题。包括线性回归,逻辑回归,梯度下降,最近邻,贝叶斯,决策树,支持向量机,集成方法,半监督学习等API 只给出函数结构,参数具体使用参考scikit-learn 官方文档 监督学习线性回归模型目标值 y 是输入变量 x 的线性组合 $y(w,x) = w_0 +w_1x_1 + … + w_px_p$ 其中 w 为系数(coef) $w_0$ 为截距(intercept)。 1. 普通最小二乘法 LinearRegression拟合一个带有系数 $w = (w_1, …, w_p)$ 的线性模型,使得数据集实际观测数据和预测数据(估计值)之间的残差平方和最小。$\underset{w}{min\,} {|| X w - y||_2}^2$ sklearn.linear_model.LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=None) from sklearn.linear_model import LinearRegressionreg = LinearRegression().fit(X,y) # 模型拟合reg.cof_ # 得到系数矩阵reg.intercept_ # 得到截距矩阵reg.score(X,y) # 误差reg.predict(X) # 预测 2. 岭回归 Ridge回归通过对系数的大小施加惩罚来解决普通最小二乘法的一些问题。 岭系数最小化的是带罚项的残差平方和。$\underset{w}{min\,} {||X w - y||_2^2 + \alpha ||w||_2^2}$,其中$\alpha \geq 0$ 是控制系数收缩量的复杂性参数(超参数) sklearn.linear_model.Ridge(alpha=1.0, fit_intercept=True, normalize=False, copy_X=True, max_iter=None, tol=0.001, solver=’auto’, random_state=None) // alpha 可以设超参数大小// tol 设置迭代最小边界// solver : {‘auto’, ‘svd’, ‘cholesky’, ‘lsqr’, ‘sparse_cg’, ‘sag’, ‘saga’} 设置求解器,拟合数据时使用的算法 sklearn.linear_model.RidgeCV( ) 内置对$\alpha$的交叉验证实现岭回归 3. 套索回归 Lasso用于拟合稀疏系数的线性模型,使用了 coordinate descent (坐标下降算法)来拟合系数,罚项 为 L1 范数。$\underset{w}{min\,} { \frac{1}{2n_{samples}} ||X w - y||_2 ^ 2 + \alpha ||w||_1}$ sklearn.linear_model.Lasso(alpha=1.0, fit_intercept=True, normalize=False, precompute=False, copy_X=True, max_iter=1000, tol=0.0001, warm_start=False, positive=False, random_state=None, selection=’cyclic’) sklearn.linear_model.LassoCV() // 对超参数$\alpha$采用交叉验证 sklearn.linear_model.LassoLars() // 采用的是最小角回归法,而不是坐标下降法进行优化 sklearn.linear_model.LassoLarsCV() //同时采用不同的验证和优化方法 sklearn.linear_model.LassoLarsIC() //对超参数$\alpha$采用 Akaike 信息准则(AIC)和贝叶斯信息准则(BIC),需要假设模型是正确的,对大样本(渐近结果)进行导出 LassoLarsCV 在寻找 $\alpha$ 参数值上更具有优势,而且如果样本数量比特征数量少得多时,通常 LassoLarsCV 比 LassoCV 要快 4. 弹性网络 ElasticNetLasso 和 Ridge 结合,对普通的线性回归做了正则化,但是它的损失函数既不全是 L1 的正则化,也不全是 L2 的正则化,而是用一个权重参数 ρ 来平衡 L1 和 L2 正则化的比重适合只有少量参数是非零稀疏的模型$\underset{w}{min\,} { \frac{1}{2n_{samples}} ||X w - y||_2 ^ 2 + \alpha \rho ||w||_1 +\frac{\alpha(1-\rho)}{2} ||w||_2 ^ 2}$ sklearn.linear_model.ElasticNet(alpha=1.0, l1_ratio=0.5, fit_intercept=True, normalize=False, precompute=False, max_iter=1000, copy_X=True, tol=0.0001, warm_start=False, positive=False, random_state=None, selection=’cyclic’) ElasticNetCV() 可以通过交叉验证来设置参数 $\alpha$ 和 $\rho$ 5. Multitask 多任务可以实现多元回归稀疏模型的预测,即多个线性模型共同拟合有MultiTaskLasso(),MultiTaskLassoCV(),MultiTaskElasticNet(),MultiTaskElasticNetCV() 6. 正交匹配追踪法(OMP)OrthogonalMatchingPursuit( )OrthogonalMatchingPursuitCV( ) 7. 贝叶斯回归 8. 稳健回归 9. 多项式回归 logistic 线性分类模型解决分类问题的线性模型,将单次实验的结果输出为概率进行分类$C \sum_{i=1}^n \log(\exp(- y_i (X_i^T w + c)) + 1) $可以选择 L1,L2 或 Elastic-Net 正则化进行约束 sklearn.linear_model.LogisticRegression(penalty=’l2’, dual=False, tol=0.0001, C=1.0, fit_intercept=True, intercept_scaling=1, class_weight=None, random_state=None, solver=’warn’, max_iter=100, multi_class=’warn’, verbose=0, warm_start=False, n_jobs=None, l1_ratio=None)// penalty 参数可以设置正则化参数// C 用$1/{\lambda}$表示的正则化强度参数// solver : str, {‘newton-cg’, ‘lbfgs’, ‘liblinear’, ‘sag’, ‘saga’} 选择优化算法,详细使用说明见官方文档// class_weight 可以设置各类型的权重// l1_ration 设置 Elastic-Net 中 ρ 控制正则化 L1 与正则化 L2 的强度 from sklearn.linear_model import LogisticRegressionreg = LogisticRegression().fit(X,y) # 模型拟合reg.cof_ # 得到系数矩阵reg.intercept_ # 得到截距矩阵reg.score(X,y) # 误差reg.predict(X) # 得到预测的分类矩阵reg.predict_proba(X) # 得到预测的概率 LogisticRegressionCV( ) 实现了内置交叉验证,可以找出最优的 C 和 l1_ratio 参数 SGD 随机梯度下降可以拟合线性的回归和分类模型,在样本量很大时尤为有用,选择和函数时要避免过拟合。SGDClassifier() 和 SGDRegressor() 分别用于拟合分类问题和回归问题的线性模型,可使用不同的(凸)损失函数,支持不同的惩罚项。 最近邻能够应用于决策边界非常不规则的分类情景 NearestNeighborsBallTreeKDTree 最近邻分类属于基于实例的学习或非泛化学习:它不会去构造一个泛化的内部模型,而是简单地存储训练数据的实例。 决策树决策树便于理解和解释,能够处理数值型数据和分类数据;但是容易产生一个过于复杂的模型,泛化性能会很差,结果不稳定,可以通过决策树的集成来得到缓解。如果某些类在问题中占主导地位会使得创建的决策树有偏差,建议在拟合前先对数据集进行平衡。 分类标准为最小化交叉熵(ID3),熵增益(C4.5)或基尼系数(Cart) sklearn.tree.DecisionTreeClassifier(criterion=’gini’, splitter=’best’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=None, random_state=None, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, class_weight=None, presort=False)// criterion 选择分类标准,可以使用”gini”或者”entropy”// splitter 设置特征划分标准// max_feature 划分的最大特征数// max_depth 选择树的最大深度// min_sample_split 设置最小样本分类// min_sample_leaf 设置最小样本叶子数// max_leaf_nodes 最大叶子节点数// class_weight 设置类别权重// presort 设置数据预排序 from sklearn.tree import DecisionTreeClassifierclf = DecisionTreeClassifier().fit(X,y)clf.n_class_ # 分类数量clf.n_features_ # 特征数量clf.n_outputs_ # 输出数量clf.tree_ # 得到分类树clf.get_depth() # 得到分类深度clf.get_n_leaves() # 得到叶子节点数clf.predict(X) # 返回预测矩阵clf.predict_proba(X) # 返回预测的概率clf.score(X,y) # 返回训练分数 决策树回归模型 sklearn.tree.DecisionTreeRegressor() (不常用) 可以使用 export_graphviz 导出器以 Graphviz 格式导出决策树,结果保存为 pdf;Jupyter notebook 也可以自动内联式渲染这些绘制节点 # outputimport graphvizdot_data = tree.export_graphviz(clf, out_file=None,\ feature_names=iris.feature_names,\ class_names=iris.target_names, \ filled=True, rounded=True, \ special_characters=True)graph = graphviz.Source(dot_data)graph.render("classification_result")# show in Jupytergraph 支持向量机可用于分类,回归和异常检测,在高维空间中非常高效,SVC, NuSVC 和 LinearSV 内核岭回归核函数 朴素贝叶斯GaussianNBMultinomialNBComplementNBBernoulliNB 集成方法1. Bagging在原始训练集的随机子集上构建一类黑盒估计器的多个实例,然后把这些估计器的预测结果结合起来形成最终的预测结果,在构建模型的过程中引入随机性,来减少基估计器的方差。 sklearn.ensemble.BaggingClassifier(base_estimator=None, n_estimators=10, max_samples=1.0, max_features=1.0, bootstrap=True, bootstrap_features=False, oob_score=False, warm_start=False, n_jobs=None, random_state=None, verbose=0)// base_estimator 设置分类估计器,默认为决策树,可设置其它分类模型// n_estimators 设置估计器的数量// bootstrap 设置样例抽取是否放回// bootstrap_features 设置特征抽取是否有放回// oob_score 设置是否用额外的样本来评估泛化精度 from sklearn.ensemble import BaggingClassifierclf = BaggingClassifier().fit(X,y)clf.predict(X)predict_proba(X)score(X, y) 2. 随机森林随机森林中的每棵树构建时的样本都是由训练集经过有放回抽样得到。在构建树的过程中进行结点分割时,选择的分割点不再是所有特征中最佳分割点,而是特征的一个随机子集中的最佳分割点,偏差通常会有略微的增大;但由于取了平均,总体上模型的泛化能力会更好。 sklearn.ensemble.RandomForestClassifier(n_estimators=’warn’, criterion=’gini’, max_depth=None, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_features=’auto’, max_leaf_nodes=None, min_impurity_decrease=0.0, min_impurity_split=None, bootstrap=True, oob_score=False, n_jobs=None, random_state=None, verbose=0, warm_start=False, class_weight=None)// n_estimators 调整森林里树的数量// max_features 分割节点时考虑的特征的随机子集的大小。使用 max_features = sqrt(n_features)是比较好的默认值// max_depth = None 和 min_samples_split = 2 结合可以生成完全树 极限随机树 ExtraTreesClassifier() 完全随机树构成森林 RandomTreesEmbedding() 2. 梯度提升回归树(GBRT)GBRT 保证迭代的每一个阶段中选择损失最小的决策树,达到全局的最小损失$Fm(x) = F{m-1}(x) + \arg\min{h} \sum{i=1}^{n} L(yi,F{m-1}(x_i) - h(x))$GBRT 具有强大的预测能力和鲁棒性,但是扩展性不够好 GradientBoostingClassifier(loss=’deviance’, learning_rate=0.1, n_estimators=100, subsample=1.0, criterion=’friedman_mse’, min_samples_split=2, min_samples_leaf=1, min_weight_fraction_leaf=0.0, max_depth=3, min_impurity_decrease=0.0, min_impurity_split=None, init=None, random_state=None, max_features=None, verbose=0, max_leaf_nodes=None, warm_start=False, presort=’auto’, validation_fraction=0.1, n_iter_no_change=None, tol=0.0001)// loss 设置损失函数,默认为 deviance($-log_2$ 似然损失函数)// learning_rate 设置学习步长// subsample 设置每次子训练集的采样,1 为全采样,一般可设置为 0.5 3. AdaBoost通过反复修改数据权重来训练一些弱学习器,由这些弱学习器的预测结果通过加权投票(或加权求和)的方式组合, 得到最终的预测结果。$Fm(x) = F{m-1}(x) + \gammam \sum{i=1}^{n} \nablaF L(y_i, F{m-1}(xi))$$\gamma_m$代表学习步长,通过计算损失最小的梯度下降$\gamma_m = \arg\min{\gamma} \sum{i=1}^{n} L(y_i, F{m-1}(xi) - \gamma \frac{\partial L(y_i, F{m-1}(xi))}{\partial F{m-1}(x_i)})$得出 初始化时,将所有弱学习器的权重都设置为 $w_i = 1/N$ ,接下来的连续迭代中,样本的权重逐个地被修改。上一轮迭代中被预测为错误结果的样本的权重将会被增加,而那些被预测为正确结果的样本的权重将会被降低。通过不断得到最快梯度下降的权重来减小损失函数。 sklearn.ensemble.AdaBoostClassifier(base_estimator=None, n_estimators=50, learning_rate=1.0, algorithm=’SAMME.R’, random_state=None)// base_estimator 设置弱学习器,默认 DecisionTreeClassifier(max_depth=1)// n_estimator 设置最大集成数量// learning_rate 设置学习速率 4. 投票分类器 最小角回归(LARS):逐步寻找与响应最有关联的预测。当有很多预测有相同的关联时,它并不会继续利用相同的预测,而是在这些预测中找出应该等角的方向。高效但对噪声敏感。]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>python</tag>
</tags>
</entry>
<entry>
<title><![CDATA[科幻/奇幻书库(top100)]]></title>
<url>%2F2019%2F05%2F21%2Ffantasy-top100%2F</url>
<content type="text"><![CDATA[个人书库,收集科幻类和奇幻类的书籍,不定期更新。 [x] 1.《魔戒之王》(奇幻)——J.R.R. 托尔金 所有奇幻文学的鼻祖,当然,赢得了我们最顶端的位置。除了全然独立创造了奇幻文学类型和影响了几代作家之外,托肯恩的传说讲述了一个宏大的故事。 2.《Amber 历代志》(奇幻)——罗杰.泽拉兹内Amber(琥珀)是惟一真实的世界。所有其他的世界,包括地球,只不过是幻像。柯文王子,Amber 王座合法的继承者,必须征服这些交错的真实,反抗恶魔的压迫,并且还要在他自己残酷的家族体系中存活下来去赢得王冠。 3.《安德的游戏》(奇幻)——奥森.斯科特.卡德仅仅八岁,安德.威金斯就成为地球上最优秀的军事天才。面临着战争的现实,安德选择了离开军队而成为了一名“言灵者”、一名顾问、真理的搜寻者和在需要咨询的家族中做仲裁人。不幸地是,上天赋予了他另外的任务。 4.《神经漫游者》(科幻)——威廉.吉布森一个耗尽了好运的黑客、同时也是一个做梦都想敛财的家伙发现了一名新生 AI 的秘密。网际庞克第一次被提出的著作,也是吉布森众多作品的第一部。 5.《异教徒汤玛斯.寇文能历代记》(奇幻)——史蒂芬.R..唐纳森一个真实世界的麻疯病人,汤玛斯.寇文能被传送到一个由污浊的、邪恶的力量包围的幻想世界。只有用他随身所携之“离奇魔术”签订的契约才能解救这个世界,但是他并不相信这个幻想世界的存在。 [x] 6.《基地》(科幻)——艾萨克.阿西莫夫 陷入衰落的银河帝国和控制了杀伤性机械的科学家神秘社会的史诗故事。 7.《沙丘》(科幻)——弗兰克.哈伯特沙丘系列的第一部讲述了宇宙中最强大的灵媒,波尔.阿特雷兹的事迹,他在学习应对政治上的阴谋和沙漠行星阿拉吉斯环境上的荒凉的同时也在平衡着自己不断增长的力量。 8.《艾尔瑞克》(奇幻)——迈克尔.摩考克一名白子战士/巫师在一次死亡竞赛中找到一柄吸魂剑而且在“秩序”和“混乱”之间的终极打击下拾起了它。 9.《高堡中的男人》(科幻)——菲利浦.k..迪克充满了偏执狂和复杂真实的游戏,这种“假如纳粹德国获胜”的剧情是曾经被写过的最非主流的历史。 [x] 10.《1984》(科幻)——乔治.奥维尔 真诚的讲你会喜欢这本书的。它是一本你要独自看的书;没有其他人在身边。你会在每天晚餐后花上二个小时看这本书;“荧光屏”能确保这一点。老大哥会成为你的朋友。 11.《休伯利安》(科幻)——丹.西蒙丝伯劳鸟:一种用思想来停止时间的终极杀人机器。霸权/人工智能同盟:一个支配整个银河的帝国。驱逐者:经过万年进化、决心推翻霸权的猿人。将这些综合在一起你就会得到一场世界末日善恶的决战。 12.《星星,我的目的地》(科幻)——阿尔弗雷德.贝斯特当格雷.福伊尔熬过了螺旋陷阱、发下报复的誓言时,他将自己改造成了一个有穿梭宇宙能力的全能的准超人。 13.《泰格纳》(奇幻)——盖伊.盖瑞尔.凯为了报仇,一名强大的巫师将泰格纳王国从现实中清除了。但是一小群英雄依靠着他们故国的记忆,寻求将泰格纳再一次重现在它原来的地方。 14.《弗兰肯斯坦》(科幻)——玛莉.雪莱一个疯狂科学家的创造物、一个用死人身体部分拼合的怪物和怪物争取世人承认他人类身份而进行抗争的经典故事。 15.《机器人会不会梦到电子羊?》(科幻)——菲利普.k..迪克一位银翼杀手警察被分配去追捕佯装成人的机器人而且在这一过程中寻究 “人类” 的定义。 16.《莎拉娜之剑》(奇幻)——泰瑞.布鲁克斯“莎拉娜”系列的第一本将施.欧姆斯福德置于反对邪恶的法术士王和他的骷髅随从的争斗中。在通俗化的现代奇幻文学中这本书是很关键的。 17.《阿努比斯之门》(科幻)——提姆.鲍尔斯一位现代学者实现了时间旅行,变更了身份、神气活现并且享受着 1810 年伦敦的魅力。如同查理斯.狄更斯遇到了印地安那.琼斯。 18.《电光》(科幻)——迪恩.库恩兹一位来自过去的时间旅行者试图阻止纳粹德国对现在的改变。 19.《提升三部曲》(科幻)——大卫.布林横跨银河的——包括有感觉力的海豚和黑猩猩——所有其它种族都通过基因改造或者 “提升”获得了智力并且要为他们的恩人献出他们的一生。人类却不是这样,他们把自己留在宇宙图腾的最底部,反对着科学高层者和时常怀有敌意的种族。 20.《环形世界》(科幻)——拉里.尼文一支星际远征队迫降到一个直径 1.9 亿英里形如呼啦圈的人造行星上。幸存者必须与最初建设者留下的蛮族后代作战,方能穿越环形世界找到答案。 21.《时间机器》(科幻)——H.G.威尔斯一个时间旅客在西元 802701 年目击了一场温顺又美丽的伊洛人和居住在地下无情的莫洛克人之间的战争。 22.《法夫哈德和老练的搜寻者》(奇幻)——弗瑞兹.雷伯一个野蛮人和老练的小偷搭伴而行,笨手笨脚地历经了一些暗杀者公会、致命的巫师和诡计多端的神制造的意外。 23.《火星公主》(科幻)——艾德加.赖斯.伯洛夫斯“约翰.卡特”系列的第一部,一个盟军士兵发现自己被传送到了火星,并在那里赢得了战士的荣誉。 [x] 24.《银河旅行者指南》(科幻)——道格拉斯.亚当斯 这本书开创了一个由五本书组成的系列。亚瑟.登特仅仅在地球因银河高速公路而被摧毁之前被搭救。他和他的同伴福特.普瑞菲特偶会一个偏执的机器人、拜访了撒法人的世界并且勇敢地面对了沃根星球的威胁。 25.《末日逼近》——斯蒂芬.金一种病毒毁灭了世界上大部份人口。当仅有的一小群人挣扎着重建文明时,恶魔的力量威胁着美洲的幸存者们。 26.《亚瑟王和他的圆桌骑士》(奇幻)——汤姆斯.马罗礼爵士亚瑟王故事的最可靠的选集——从兰斯洛特的背叛到莫德雷德的出生到影子骑士。 [x] 27.《我,机器人》(科幻)——艾萨克.阿西莫夫 科幻小说中为智能机器人设定了标准的短篇故事。最著名的是设定出现在被公认的机器人三定律。 28.《月亮是一个严厉的妇人》(科幻)——罗伯特.海因莱茵月亮是成为一个被铁腕政权统治的严酷的殖民地。市民想获得自由,于是求助于一台有自我意识的计算机展开反抗计划。 29.《水洼》——理查德.亚当斯完全从一只兔子的眼光来看待搜寻新的家园和为生存而竞争。一本独特的取材于《出埃及记》的圣经故事。 30.《华氏 451》(科幻)——雷.布雷德伯里在盖伊.蒙太哥生活的世界里,消防员不用读书;他们焚烧书籍。盖伊喜欢他的工作。十年的消防员生涯,他从没问过隐藏在焚烧书籍背后或者它给他带来乐趣的原因……直到一个 17 岁的女孩告诉他,过去这里的人们并不惧怕阅读。 [x] 31.《霍比特人》(奇幻)——J.R.R. 托尔金 霍比特矮人比尔博.巴金斯,巫师甘道夫和 13 个矮人着手到大孤山中探索并取回矮人的宝物。侏儒、小妖精、巨大的蜘蛛和罪恶的龙,Smaug,遍布他们的旅途中。 32.《赫利康尼亚》(科幻)——布莱恩.奥尔迪斯在一颗他们的一年相当于我们 3000 年并且冬天如同冰河纪的行星上,文明兴衰轮回。 33.《新日之书》(奇幻)——吉尼.渥尔夫有多少个系列丛书以拷打者为主角呢?这本书中一名年轻的拷打者学徒毕业了,成为一个完全的刽子手,他朝着世界的统治者前进,成为人类的救星,当然,最终,不免一死。 [x] 34.《格利佛游记》(奇幻)——乔纳森.斯韦夫特 一个船只遇难的生还者偶遇到除了在一系列政治讽刺小说中所拥有的事物以外,还有微型人、巨人和超智人、会说话的马人。 35.《记忆杀手》(科幻)——斯比德.鲁滨逊当你发现某个人能清除记忆时你会怎么做?记忆杀手——死亡杀手的第一部中篇小说 ── 追踪了两个人的旅程。他们被他们生命中难以抗拒的秘密所吸引,最终在一个谜一般的组织里会合,这个组织负责开发一种可以让人单纯的快乐而死的技术。这同时也是第一种洗脑的永久兴方法。主角们决定要阻止这个企业,尽管他们知道这个会送了他们的命。第一次读这本小说的时候,你会觉得它是本恐怖的神秘小说。第二次,你会发现它提供了丰富的人物描写,然后你会问:是什么使得人生值得一活? 36.《血里的音乐》(科幻)——格鲁格.贝尔一个天才的研究员发明出生物芯片——智慧细胞——而且将它们注射到自己体内。它们像疾病一样扩散起来,带来了《启示录》般的结果。 37.《绿里》——斯蒂芬.金令人毛骨悚然的死亡侵入囚犯中间,令他们仿佛面对电椅一般。 38.《夜访吸血鬼》(奇幻)——安妮.赖斯将有关吸血鬼的哥德式的神秘带进现代旧金山的夜晚的小说。 39.《星际船伞兵》(科幻)——罗伯特.海因莱茵一个未来的新兵通过了宇宙中的最残酷的海军新兵训练基地的锤炼——并且投入反抗人类最致命敌人的战争之中。忘掉电影去读书吧。 [x] 40.《纳尼亚年代记》(奇幻)——C.S.路易斯 这个系列包含《狮子》、《巫婆》和《衣橱》,系列中最有名的一本,英格兰某地的四个孩子走进一个衣橱,里面浮现出一个有魔力的纳尼亚大陆,这个大陆上有半人半羊的农牧神和会说话的海狸,整个大陆处于由白魔女施下的永恒的冬天的规则和符咒之下。 41.《启示录三部曲》——罗伯特.施和罗伯特.安顿.威尔逊启示录系列的三本书只有部分是想像的著作。它们全面解决了我们这个时代中的谜团,从到底是谁射杀了肯尼迪到为什么一美元钞票上有金字塔。 42.《看守者》(科幻)——迪恩.库恩兹基因实验创造出二只超智生物。一只是疯狂的邪恶生物,逃走了。另一个能阻止他的是他的“兄弟”——一只被命名为爱因斯坦的被驯养的狗。 43.《被毁的人》(科幻)——阿尔弗雷德.贝斯特一个毛骨悚然的谋杀/悬疑故事,回答了这样一个问题,“在 24 世纪的精神感应流行的社会中该怎样定义谋杀?” 44.《埃姆菲瑞尔》——杰克.万斯在行星哈默上,统治者将机械化和大生产视为违法,藉以限制工人的产量来使得他们贫穷潦倒。吉尔.塔沃克,一名雕刻师的儿子,为推翻传统体系和为工人阶级赢得公平待遇而工作。 45.《奥兹法师》(奇幻)——L.弗兰克.鲍姆桃乐丝寻找回家路途时和她的朋友们游历了一个奇幻世界。这是奥兹系列的第一部,比那部经典电影包含多得多的内容,例如与丑陋的锤头的偶遇和铁皮人的由来。唉,然而没有飞天猴子。 46.《世界大战》(科幻)——H.G.威尔斯经典的外星人入侵故事,有高度发达科技的火星征服者却带有巨大的致命弱点。 47.《传说中的森林》(奇幻)——罗伯特.霍德斯托克凯尔特人和古英语的神话来源自富有生气的原始森林地带,那里会从人们无意识中产生活生生的“幽灵”。 48.《动物农场》(科幻)——乔治.奥威尔暴动的农场家畜们逃离了它们的压迫者建立起一个家畜乌托邦。 49.《公主新娘》(奇幻)——威廉.高曼一个活灵活现的浪漫又刺激的故事……加上非同寻常大小的老鼠。 50.《时光之轮》(奇幻)——罗伯特.乔丹一个世代终结了,另一个世代又兴起。命运之网在每一个轮回里让那些古英雄们和反面角色得以重生,并由此展开一系列故事。在漫长的年代更迭中,黑暗之王被沙约尔.弗尔施法囚禁在他的山脉监狱中。他渴望逃脱,并且把所有从他手心逃掉的家伙全部杀掉,同时他的爪牙在大陆上暗中破坏、操纵并用其它方法促成他邪恶的愿望。一个农夫的孩子,安特.兰德.al\’Thor,对于他所在的小村庄外的事情一无所知。但是当一个神秘的女人到来使他看到了正在逼近的邪恶时,兰德和他的伙伴出发去寻求永久改变世界的办法。你知道,兰德是再生的龙,当时最强大的男法师。他拥有强大的力量可以举起整个城市、可以改写历史、可以挑战黑暗之王——但这种力量慢慢的使他发了疯。 51.《死光》——斯蒂芬.金一支专门捕食虚弱的人、易受伤害的人、放荡的人的生物。一只成为你最可怕的梦魇的生物。 52.《发条橙》(科幻)——安东尼.伯吉斯当 ultraviolent.亚历克斯被捕后,他接受了将他反社会的冲动置于人工控制的治疗。没有了自由的意志还能够是一个善良的人吗? 53.《时间柱》(科幻)——格雷戈里.本福德不久的将来科学家将信息及时地送回 1962 年以拯救行星。 54.《波恩》(奇幻)——安妮.麦卡芙瑞人类骑士与善良的、飞机大小的龙进行意识连接,去对抗所有贪婪的斯瑞德.赫尔。 55.《五号屠场》(科幻)——库尔特.冯内古特战争的恐怖成为一个人在两种现实——从二战的德雷斯顿到囚禁在外星球 Tralfamadore——之间来回转换的体验。 56.《吉兆》——内尔.吉曼和泰瑞.普拉特切特在这个奇异的、世界终结的喜剧中,哈米吉多顿(世界末日善恶决战的战场)出现了,然而天使和恶魔都没有准备好面对它。 57.《菲奥尼瓦》(奇幻)——盖伊.盖乌瑞尔.凯一群现代学生被神秘地传送到一个处于危险之中的幻想世界。当一个恶毒的魔王从千年的监禁中释放出来时,学生们发现他们的命运与那些菲奥尼瓦纠缠在一起。 58.《地海法师》(奇幻)——厄休拉.K..勒吉恩一个名为盖德的男孩研究怎样成为男巫,并且最终被视为帮助重建了宇宙的平衡:光和暗、男人和女人、生存和死亡、法术和它的终极价值。 [x] 59.《2001》(科幻)——阿瑟 C.克拉克 我们是如何得知我们是什么的?这个系列回答了一个人类基本的问题。它开始于我们的猿类祖先和对生存的竞争之间联系的确立。我们被其它行星的生命视为无可救药的虚弱和数量众多。一种外部的力量通过一块巨大的黑色“独块巨石”的方式播种下了真正智慧的种子。这些第一次概念上的想法开启了一系列使我们进入未来的事件。未来的开发中,我们的好奇心引导着我们在月球上发现了另外一个这样的盒子——它是一项铁证,证明了我们不是宇宙中惟一的指挥文明!这也是一项对于我们来说无法理解的发现,如同我们千百万年以来的生存问题一样。接着,人类不断地探寻,只是在木星附近发现了另一个盒子,它带给人类更多至为重要的事件。3001 年:最后的奥德赛,系列中提到过多次的问题——不管是凶是吉——得到了最终的回答。 60.《异种生殖》——奥克塔维亚.巴特勒外星人欧安卡利拯救了地球。作为代价,欧安卡利的幸存者需要稳定的基因的交换……而且我们是交配的原料。 61.《深渊之火》(科幻)——弗纳.维格来自另一个宇宙的似神的人工智能体威胁着这个宇宙。一个群体拥有阻止它的知识,但他们被困在一颗灵长类动物的行星,那里没有空间航行或者联络的科技手段。 62.《柯南》(奇幻)——罗伯特.E..霍华德终极的野蛮英雄挫败了大量的邪恶法师,将大批恶毒的畸形怪物象垃圾一样清除,并且搭救了行星上每一位美丽的公主。然后他大吃起早餐。 63.《火星》(科幻)——金.斯坦利.罗宾逊2026 年,一对百名探险家起程拓殖火星并将其地球化。不过,并不是每个人都想那样做。 64.《灵魂之井的午夜》——杰克.L..查克大部份的宇宙实际上由一个远古的死亡种族建造的并由一台庞大的计算机控制着。无论是谁控制了计算机都等于拥有了终极力量。 65.《变色龙的符咒》——皮尔斯.安东尼在仙丝,每个人都有他们自己惟一的特殊魔术力量。不幸的是,布林克出生时却没有独特的法术,他怎么办? 66.《缝隙》(科幻)——史蒂芬.R..唐纳德森来自遥远的禁断空间的边界,埃姆昵恩,一个倾向恐怖暴行的外星种族,需要某种人类无法形容的东西——而且他们会以某些无法想象的程度来得到它。 67.《亚瑟王法庭中的康涅狄格美国佬》(科幻)——马克.吐温一个 19 世纪的男人被传送回圆桌会议发生地,在那里他通过介绍许多诸如铁路和电话等现代工具而被任命为亚瑟王的帮手。 68.《不锈钢鼠历险记》(科幻)——哈里.哈德森吉姆.迪格兹是银河中最有才气的欺诈艺术家和小偷。当他最后被捕获时,执法者只有一个选择——让他成为他们中的一员——因为要用这只老鼠去捉另一只。 69.《火星编年史》(科幻)——雷.布雷德伯里一本聚焦在人类在红色行星上以及与那些怪诞的原住民间偶遇的短篇故事集。它开始于第一次的接触和从那里的搬移。每个故事都贴上了布雷德伯里怪诞的标签。 70.《黑暗精灵》(奇幻)——R.A. 萨尔瓦多游戏相关小说最好的系列之一,介绍了崔斯特.杜垩登,一个黑暗精灵,他一出生便拥有其他精灵所不具备的或不能提供的品质:同情心。他的家乡,地下城市魔索布莱城,是一个粗暴的地方,而且他的家族通过坚守城市的金箴规则:“不留活口”而取得了它的权力位置。当崔斯特成年时,魔索布莱城中越来越多的人开始讨厌他,而且他也无法做他的社会所需要的那些邪恶行为。最后,他惹恼他的家族,成为了母系社会中的一名男性,对他的处罚就是死亡。他没有选择只有逃到到地表世界,但那里不会善待黑暗精灵,因为他们有着嗜杀者的恶名。崔斯特寻求 “善行” 社会的接受和摆脱他的过去,这导致了许多次冒险和战斗。 71.《伊甸园之西》(科幻)——哈里.哈德森地球被智能恐龙所统治;他们发现了美洲大陆,利用工具移民石器时代的人。于是血腥的战斗爆发了。 72.《美好的秘密所在》——彼得.S..比戈一个永恒的经典浪漫史,发生在两个必须通过打斗来记起曾经的生命和爱的鬼魂之间。 [x] 73.《海底两万里》(科幻)——儒勒.凡尔纳 尼摩船长在大洋中的历险和为了他们的控制权而发生的战斗。凡尔纳的鹦鹉螺号早于真正的潜水艇。 74.《内心垂死》——罗勃特.西尔弗伯格一个老去的有精神感应的人开始失去控制他的精神力量。一次进入某个被赋予了不同寻常力量的男人思想内部的迷人旅程。 75.《龙枪》(奇幻)——玛格丽特.魏丝和崔西.西克曼传说中的生物,龙,回来了——伴随着他们的是黑暗和破坏。只有一队探险者能够拯救世界……只要他们没有从内部被出卖。 76.《透镜人》(科幻)——E.E..史密斯”博士”经典的太空歌剧,讲述了男童子军般纯朴的英雄和无情的邪恶坏蛋为潮湿行星的“世界末日装置”的控制而战斗。 77.《坏东西这样来》——雷.布雷德伯里也许这是曾经被写过的最精妙的惊骇故事。狂欢节允诺实现你最大的希望,但要为此承担最高的价格。 这本书中的情景会在你的余生里经常见到。 78.《上帝眼中的微尘》——拉里.尼文和杰瑞.波内尔西元 3017 年是人类在宇宙的一个死水区域中发现智慧外星生物的一年;我们是应该迎接他们还是把他们炸成碎块? 79.《异乡异客》(科幻)——罗伯特.海因莱茵陌生人是瓦伦丁.迈克尔.史密斯,陌生的土地是地球。史密斯出生于火星,是我们第一支去那里的远征队中惟一的人类幸存者。他被火星人养大,然后被 25 年后的第二支远征队所“搭救”。他认为自己是火星人并且使用看上去与他们没有什么不同的火星人能力——悬浮术。现在,向被狼在荒野中养大的孩子一样,他必须学会怎样做人……而且同时,教他的新朋友如何看待一个火星人。他发现了性和自由性爱的乐趣(这是 60 年代那一代人令这本书非常流行的部分原因),而且试着用他火星知识来调解地球宗教许多互相冲突的教义。读者不仅看到史密斯的成长,而且得知了一系列未来地球的情况和人类社会所有的弱点。 80.《空间三部曲》(科幻)——C.S..路易斯火星生命泛滥。水覆盖下的金星移居来一些漂浮的居住用的“岛屿”。如同地球上亚瑟王对抗整个英国的地方。 81.《隐身人》(科幻)——H.G. 威尔斯一个科学家的心智和道德是他不可见的道德准则的价值。 82.《带特殊音乐的枪》(科幻)——乔纳森.莱塞姆一个私家侦探在不远的、黑暗的未来侦破一件棘手的谋杀疑案,那时残留的人类和动物生活在一起,这些动物是类似枪袋鼠那样经过增强基因达到了接近人类的智力。近乎苛刻的黑暗色调,非常搞笑。 83.《里昂内斯》(奇幻)——杰克.万斯超自然小说,充斥着仙子、巫婆和颠覆王国的阴谋——而这一切全部是在英吉利海峡下发生的。 84.《傀儡》(科幻)——琼.维格计算机朋克,谋杀秘密和政治上的阴谋扭结在这一本书中,它讲述了一只猫的故事,一个心理意义上的半人,被强给他最憎恨的人做保镖。 85.《水晶快递》(科幻)——布鲁斯.斯特灵人类最终为了空间抛弃了地球而且像哲学上那样把生物分为了两个集团。形态论者利用基因和生物工程技术改造了他们的身体去适应空间,而机械论者把信心放在制造高级人类使用的控制论增强器上。 86.《最后的独角兽》(奇幻)——彼得.S..贝格尔当一只独角兽收到其它已经消失的独角兽的音信时,她踏上了寻找她失踪的同伴的路途。她因一个草率的时代差点死去,而且她是惟一热爱人类比较久的独角兽。 87.《走向你们散落的身体》——弗利普.何塞.法默任何人都曾经死去过——你、我、希特勒、马克.吐温——死在一个陌生的外星世界。“河上世界”系列的第一本书讲述了一个孤独的探索者试图解出奇异的“来世”的秘密。 [x] 88.《沉默的羔羊》——托马斯.哈里斯 一名 FBI 侦探必须谋求一个嗜血成性的连环杀人犯的帮助来追捕到另一名连环杀人犯。 89.《深潜站》——C.J. 切立夫人类已经能够驾驶亚光速飞船探索几百光年外的宙域,这么长的距离足够在一些遥远的太阳系的两个轨道站之间建设贸易航线。深潜站处于航线的关键位置,也是通向地球防卫圈的门户。地球主管当局担心亚光速通信的间歇——有时会长达十年甚至更多——会给他们遥远的殖民地和暴发户商人的飞船带来太多的自由,但是当地球最终采取制裁措施时,一切已经太晚了:在遥远的赛汀上的科学家们已建造了第一艘超光速空间航行器,并且赛汀成为一个名为联邦的新生力量的中心。尽管深潜站已宣称自己中立,它还是夹在地球、联邦和商团武装之间,注定成为冲突的中心。 90.《献给埃基尔侬的花》(科幻)——丹尼尔.基斯一个心理上弱智的小管理员接受了一项具有突破性意义的外科手术,使得其智商提高了三倍。他拥有了天才的头脑,但却只有孩童的情感。 91.《遥远地球之歌》(科幻)——阿瑟.C..克拉克人类了解到太阳正走向爆炸,于是在地球被毁灭之前将它的基因种子进入宇宙。这是带有合理可行的空间旅行方法的硬科幻小说。 92.《钻石的四大统治者》(科幻)——杰克.查克一名间谍将他的思想复制到四个不同的身体之内,以便渗入到四个敌人的世界中并刺杀他们的统治者。 93.《剑》(奇幻)——弗瑞德.萨伯海根神武坎制造了精美的刀剑,每一把都拥有特殊的无法阻挡的力量,并且能在未曾猜想到的世界里释放它们。一开始,人类就用这些剑杀死了神。随即,事态变得狂烈起来。 94.《中转站》(科幻)——克利福德.西马克一个普通人被银河联邦雇用看守一个他们在地球上秘密安置的中转站。他能平衡对自己种族、对雇主的诚信并阻止一场核子战争吗? 95.《海怪苏醒》——约翰.怀海姆一个不寻常的“海下入侵” 假设将产生“你疯了”想法的主角波尔和杰梅紧密联系在一起。 96.《雪崩》(科幻)——内尔.斯蒂芬森第一本以网络人格和虚拟现实的初步暗示为特色的塞伯朋克小说。另外,你会喜欢上那个叫 Hiro Protagonist(日本名)的主人公,他是一名黑客、日本武士兼披萨饼快递员。 97.《满天飞翔的十字军》(科幻)——波尔.安德森黑暗时代的骑士驾驶一艘宇宙飞船征服银河,一路上将外星人教化成基督徒。 98.《穿越镜面》(奇幻)——路易斯.卡罗尔小说中讲述了爱丽丝在奇境里的故事,年轻的爱丽丝寻找归家之路,在这期间,探索了一块疯狂的、被施过魔法的大陆并且巧妙地躲过了试图伤害她的人。 99.《腐尸安慰者》(奇幻)——丹.西蒙斯一个超自然吸血鬼的社会导致其他人的痛苦并和人类头脑斗智。 100.《邮差》(科幻)——大卫.布林你曾看过一部电影关于一个人在美国邮递启示录过程中坚持自己的理念的故事。现在读一下这本书,它会更好些。 黑暗物质三部曲 [x] 猎魔人系列 [x] 克苏鲁神话 冰与火之歌 [x] 刺客信条 暮光之城 遗产三部曲 地海传奇 [x] 银河帝国 海伯利安 地铁 2033 2034 三体 魔兽世界系列 肯 福莱特 丹 布朗]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>book</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Flask Web 学习笔记2 -- URL与视图函数映射]]></title>
<url>%2F2019%2F04%2F11%2Fflask-learning2%2F</url>
<content type="text"><![CDATA[-学习笔记-通过 URL 传递参数,接收参数,利用试图函数实现参数到 URL 转换,自定义 URL 转换 URL 是 Uniform Resource Locator 的简写,统一资源定位符。一个 URL 由以下几部分组成: scheme://host:port/path/?query-string=xxx#anchor scheme:代表的是访问的协议,一般为 http 或者 https 以及 ftp 等。 host:主机名,域名,比如www.baidu.com。 port:端口号。当你访问一个网站的时候,浏览器默认使用 80 端口。 path:查找路径。比如:www.jianshu.com/trending/now,后面的trending/now就是path。 query-string:查询字符串,比如:www.baidu.com/s?wd=python,后面的wd=python就是查询字符串。 anchor:锚点,后台一般不用管,前端用来做页面定位的。 传递参数传递参数的语法是:/<参数名>/。然后在视图函数中,也要定义同名的参数。 @app.route('/')@app.route('/list/')@app.route('/p/<float:article_id>')@app.route('/u/<uuid:user_id>/')@app.route('/<any(blog,article):url_path>/<id>/') 参数的数据类型 如果没有指定具体的数据类型,那么默认就是使用string数据类型。 int数据类型只能传递int类型。 float数据类型只能传递float类型。 path数据类型和string有点类似,都是可以接收任意的字符串,但是path可以接收路径,也就是说可以包含斜杠。 uuid数据类型只能接收符合uuid的字符串。uuid是一个全宇宙都唯一的字符串,一般可以用来作为表的主键。 any数据类型可以在一个url中指定多个路径。 @app.route('/<any(blog,article):url_path>/<id>/')def detail(url_path,id): if url_path == 'blog': return '博客详情:%s' % id else: return '博客详情:%s' % id 接收用户传递的参数 第一种:使用path的形式(将参数嵌入到路径中),就是上面讲的。 第二种:使用查询字符串的方式,就是通过?key=value的形式传递的。 @app.route('/d/')def d(): wd = request.args.get('wd') return '参数是:%s' % wd URL 转换器url_for将视图函数名字后面的参数传递给url。如果传递的参数之前在url中已经定义了,那么这个参数就会被当成path的形式给url。如果这个参数之前没有在url中定义,那么将变成查询字符串的形式放到url中。 from flask import Flask,url_for,[email protected]('/list/<page>/')def my_list(page): return 'my list'print(url_for('my_list',page=1,count=2))# page作为path,count作为查询字符串# 构建出来的url:/my_list/1/?count=2 url_for 优势 将来如果修改了URL,但没有修改该 URL 对应的函数名,就不用到处去替换 URL 了 @app.route('/post/list/<page>/')def my_list(page): return 'my list'url = url_for('my_list',page=1,count=2)# 原来的url:/my_list/1/?count=2# 新构建出来的url:/post/my_list/1/?count=2 url_for 会自动的处理那些特殊的字符,不需要手动去处理。 @app.route('/login/')def login(): return 'login'url = url_for('login',next='/')# 会自动的将`/`编码,不需要手动去处理。# url=/login/?next=%2F 自定义 URL 转换器URL 参数的数据类型通过routing.py中的Unicode/Float/Any/Path/Number Converter等类指定,使用了默认转换器 可以自定义类型 URL 转换器和运算符 URL 转换器 自定义方法 实现一个类,继承自BaseConverter。 在自定义的类中,重写regex,也就是这个变量的正则表达式。 将自定义的类,映射到app.url_map.converters上。 from flask import Flask,url_forfrom werkzeug.routing import BaseConverter# 自定义手机号码的变量URL转换class TelephoneConveter(BaseConverter): regex = r'1[85734]\d'app.url_map.converters['tel'] = TelephoneConverter# 使用自定义的数据类型@app.route('/telephone/<tel:my_tel>/')def my_tel(my_tel): return '您的手机号码是:%s' % my_tel############################ 自定义+号运算符解析class OpratorConverter(BaseConverter):def to_python(self, value): # 这个方法的返回值,将会传递到view函数中作为参数 return value.split('+')def to_url(self, value): # 在调用url_for函数的时候生成符合要求的URL形式 return "+".join(value) # return "hello"app.url_map.converters['oprator+'] = OpratorConverter# 使用自定义[email protected]('/posts/<oprator+:boards>/')def posts(boards): print(boards) return "您提交的板块是:%s" % boards URL 重定向重定向在页面上体现的操作就是浏览器会从一个页面自动跳转到另外一个页面。比如用户访问了一个需要权限的页面,但是该用户当前并没有登录,因此我们应该给他重定向到登录页面。 永久性重定向:http的状态码是301,多用于旧网址被废弃了要转到一个新的网址确保用户的访问。 暂时性重定向:http的状态码是302,表示页面的暂时性跳转。比如访问一个需要权限的网址,如果当前用户没有登录,应该重定向到登录页面,这种情况下,应该用暂时性重定向。 flask中有一个函数叫做redirect,可以重定向到指定的页面。 from flask import Flask,request,redirect,url_forapp = Flask(__name__)@app.route('/login/')def login(): return '这是登录页面'@app.route('/profile/')def profile(): if request.args.get('name'): return '个人中心页面' else: # redirect 重定向 return redirect(url_for('login')) 视图函数的响应 可以返回字符串:flask 会创建 werkzeug、wrappers、Response 对象,状态码 200,MIME 类型test/html,然后返回 Response 对象 from flask import [email protected]('/list/')def list(): Response('Hello World!')# Response('Hello World!',status=200,mimetype='text/html') 还可以通过 make_response 进行创建 form flask import [email protected]('/list/')def list(): return make_response('list page.') 可以返回元组:元组的形式是(Response,Status,header)不一定三个都要写,写两个也是可以的,status 返回 200,header 为列表或字典。返回的元组,其实在底层也是包装成了一个Response对象。return 'list',200,{'NAME':'kevin'} @app.errorheader(404)def not_found(): return 'not found',404 直接返回合法的响应对象 resp = Response('list')resp.set_cookie('country','china')return resp 以上条件不满足,则进行自定义响应 继承自Response类。实现方法force_type(cls,response,environ=None)。指定app.response_class为你自定义的Response对象。如果视图函数返回的数据,不是字符串,也不是元组,也不是 Response 对象,那么就会将返回值传给force_type,然后再将force_type的返回值返回给前端。 class myResponse(Response): def force_type(cls, response, environ=None): return Response('return error.')app.response_class = myResponse # 使用jsonify将返回的格式转换成json格式from flask import jsonify...class myResponse(Response): def force_type(cls, response, environ=None): if isinstance(response,dict): # jsonify除了将字典转换成json对象,还将改对象包装成了一个Response对象 response = jsonify(response) # 调用父类 return super(myResponse, cls).force_type(response, environ)app.response_class = myResponse]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>flask</tag>
</tags>
</entry>
<entry>
<title><![CDATA[c++中的智能指针]]></title>
<url>%2F2019%2F04%2F05%2Fptr%2F</url>
<content type="text"><![CDATA[由于 C++ 语言没有自动内存回收机制,程序员每次 new 出来的内存都要手动 delete,用智能指针便可以有效缓解这类问题。 对于编译器来说,智能指针实际上是一个栈对象,并非指针类型,在栈对象生命期即将结束时,智能指针通过析构函数释放有它管理的堆内存。所有智能指针都重载了“operator->”操作符,直接返回对象的引用,用以操作对象。访问智能指针原来的方法则使用“.”操作符。 访问智能指针包含的裸指针则可以用 get() 函数 智能指针包含了 reset() 方法,如果不传递参数(或者传递 NULL),则智能指针会释放当前管理的内存。如果传递一个对象,则智能指针会释放当前对象,来管理新传入的对象。 编写测试类来辅助分析 class Simple { public: Simple(int param = 0) { number = param; std::cout << "Simple: " << number << std::endl; } ~Simple() { std::cout << "~Simple: " << number << std::endl; } void PrintSomething() { std::cout << "PrintSomething: " << info_extend.c_str() << std::endl; } std::string info_extend; int number;}; std::auto_ptr包含头文件 #include<memory> 便可以使用std::auto_ptr 能够方便的管理单个堆内存对象 用法一:std::auto_ptr<MyClass>m_example(new MyClass()); 用法二:std::auto_ptr<MyClass>m_example;m_example.reset(new MyClass()); 用法三(指针的赋值操作):std::auto_ptr<MyClass>m_example1(new MyClass());std::auto_ptr<MyClass>m_example2(new MyClass());m_example2=m_example1; 使用示例void TestAutoPtr() { std::auto_ptr<Simple> my_memory(new Simple(1)); // 创建对象 if (my_memory.get()) { // 判断智能指针是否为空 my_memory->PrintSomething(); // 使用 operator-> 调用智能指针对象中的函数 my_memory.get()->info_extend = "Addition"; // 使用 get() 返回裸指针,然后给内部对象赋值 my_memory->PrintSomething(); // 再次打印,表明上述赋值成功 (*my_memory).info_extend += " other"; // 使用 operator 返回智能指针内部对象,然后用“.”调用智能指针对象中的函数 my_memory->PrintSomething(); // 再次打印,表明上述赋值成功 }} // my_memory 栈对象即将结束生命期,析构堆对象 Simple(1) 执行结果为:Simple: 1PrintSomething:PrintSomething: AdditionPrintSomething: Addition other~Simple: 1 不能使用 = 操作符void TestAutoPtr2() { std::auto_ptr<Simple> my_memory(new Simple(1)); if (my_memory.get()) { std::auto_ptr<Simple> my_memory2; // 创建一个新的 my_memory2 对象 my_memory2 = my_memory; // 复制旧的 my_memory 给 my_memory2 my_memory2->PrintSomething(); // 输出信息,复制成功 my_memory->PrintSomething(); // 崩溃 }} my_memory2 = my_memory这行代码,my_memory2 完全夺取了 my_memory 的内存管理所有权,导致 my_memory 悬空,最后使用时导致崩溃。 release() 函数问题void TestAutoPtr3() { std::auto_ptr<Simple> my_memory(new Simple(1)); if (my_memory.get()) { my_memory.release(); }} //最终执行结果为 Simple:1,没有被析构,导致内存泄露 调用 release() 函数释放内存,不会释放对象,仅仅归还所有权,要自己 delete 或使用 reset()函数销毁对象 //代码修正void TestAutoPtr3() { std::auto_ptr<Simple> my_memory(new Simple(1)); if (my_memory.get()) { Simple* temp_memory = my_memory.release(); delete temp_memory; // 或者直接 my_memory.reset(); 释放 my_memory 内部管理的内存 }} 注意事项使用 std::auto_ptr 时,绝对不能使用“operator=”操作符,这会夺取内存管理所有权std::auto_ptr 的 release() 函数不会释放对象,仅仅归还所有权。std::auto_ptr 最好不要当成参数传递(读者可以自行写代码确定为什么不能)。std::auto_ptr 的“operator=”问题,有其管理的对象不能放入 std::vector 等容器中。C++11 中,std::auto_ptr 已经被弃用 自 C++11 起,C++标准提供两大类型的智能指针:shared_ptr 和 unique_ptr std::shared_ptrshared_ptr 实现共享式拥有(shared ownership)概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用(reference)被销毁”时候释放。为了在结构复杂的情境中执行上述工作,标准库提供了 weak_ptr、bad_weak_ptr 和 enable_shared_from_this 等辅助类。 shared_ptr 本身提供默认内存释放器(default deleter),调用的是 delete,也可以自定义释放器 默认内存释放器并不能释放数组内存空间,要我们自己提供内存释放器 成员函数use_count 返回引用计数的个数unique 返回是否是独占所有权( use_count 为 1)swap 交换两个 shared_ptr 对象(即交换所拥有的对象)reset 放弃内部对象的所有权或拥有对象的变更, 会引起原有对象的引用计数的减少get 返回内部对象(指针) 示例 std::shared_ptr<int> sp0(new int(2));std::shared_ptr<int> sp1(new int(11));std::shared_ptr<int> sp2 = sp1;printf("%d\n", *sp0); // 2printf("%d\n", *sp1); // 11printf("%d\n", *sp2); // 11sp1.swap(sp0);printf("%d\n", *sp0); // 11printf("%d\n", *sp1); // 2printf("%d\n", *sp2); // 11std::shared_ptr<int> sp3(new int(22));std::shared_ptr<int> sp4 = sp3; // 或 auto sp4 = sp3printf("%d\n", *sp3); // 22printf("%d\n", *sp4); // 22sp3.reset();printf("%d\n", sp3.use_count()); // 0printf("%d\n", sp4.use_count()); // 1printf("%d\n", sp3); // 0 注意事项shared_ptr 会因循环引用造成无法释放资源与 weak_ptr 一起工作时, weak_ptr 在使用前需要检查合法性shared_ptr 不支持数组, 如果使用数组, 需要自定义删除器 std::weak_ptrweak_ptr 设计的目的是为配合 shared_ptr 而引入的一种智能指针来协助 shared_ptr 工作, 它只可以从一个 shared_ptr 或另一个 weak_ptr 对象构造, 它的构造和析构不会引起引用记数的增加或减少。 weak_ptr 没有重载*和->但可以使用 lock 获得一个可用的 shared_ptr 对象. 注意, weak_ptr 在使用前需要检查合法性。 weak_ptr 支持拷贝或赋值, 但不会影响对应的 shared_ptr 内部对象的计数。 成员函数expired 用于检测所管理的对象是否已经释放, 如果已经释放, 返回 true; 否则返回 falselock 用于获取所管理的对象的强引用(shared_ptr). 如果 expired 为 true, 返回一个空的 shared_ptr; 否则返回一个 shared_ptr, 其内部对象指向与 weak_ptr 相同。use_count 返回与 shared_ptr 共享的对象的引用计数.reset 将 weak_ptr 置空. 使用 weak_ptr 解决 shared_ptr 因循环不能释放资源的问题使用 shared_ptr 时, shared_ptr 为强引用, 如果存在循环引用, 将导致内存泄露. 而 weak_ptr 为弱引用, 可以避免此问题 class CA{public: CA(){} ~CA(){PRINT_FUN();}private: std::weak_ptr<CB> m_spb;};class CB{public: CB(){}; ~CB(){PRINT_FUN();};private: std::shared_ptr<CA> m_spa;};std::shared_ptr<CA> spa(new CA); // 通过调用weak_ptr,释放CA内存时不影响CBstd::shared_ptr<CB> spb(new CB); std::unique_ptrunique_ptr 实现独占式拥有(exclusive ownership)或严格拥有(strict ownership)概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(resourece leak)——例如“以 new 创建对象后因为发生异常而忘记调用 delete”——特别有用。 unique_ptr 不支持拷贝和赋值,但是可以调用 release 或 reset 将指针的所有权从一个(非 const) unique_ptr 转移到另一个std::unique_ptr<A> up1(new A(5));std::unique_ptr<A> up2(up1); // 错误, unique_ptr 不支持拷贝std::unique_ptr<A> up2 = up1; // 错误, unique_ptr 不支持赋值std::unique_ptr<int> up2(up1.release()); // 正确 unique_ptr 不支持拷贝, 但是可以从函数中返回, 甚至返回局部对象 std::unique_ptr<Ty> Clone(const Ty& obj){ std::unique_ptr<Ty> temp = std::unique_ptr<Ty>(new Ty(obj)); return temp; // 或直接 return std::unique_ptr<Ty>(new Ty(obj))} unique_ptr 支持管理数组 成员函数get 获得内部对象的指针release 放弃内部对象的所有权,将内部指针置为空, 返回所内部对象的指针, 此指针需要手动释放reset 销毁内部对象并接受新的对象的所有权(如果使用缺省参数的话,也就是没有任何对象的所有权, 此时仅将内部对象释放, 并置为空)swap 交换两个 shared_ptr 对象(即交换所拥有的对象)std::move(name) 所有权转移(通过移动语义), 所有权转移后,变成“空指针” 防内存泄漏代码改进 int main(){ int *ptr = new int(0); return 0;} // 内存泄露 int main(){ int *ptr = new int(0); delete ptr; // 释放内存 return 0;} // ptr成空悬指针 int main(){ int *ptr = new int(0); delete ptr; // 释放内存 ptr = nullptr; return 0;} //使用 unique_ptrint main(){ unique_ptr<int> ptr(new int(0)); return 0;} boost::scoped_ptrboost::shared_ptrboost::scoped_arrayboost::shared_arrayboost::weak_ptrboost:: intrusive_ptr参考资料:https://blog.csdn.net/xt_xiaotian/article/details/5714477https://www.cnblogs.com/xiehongfeng100/p/4645555.htmlhttps://www.cnblogs.com/diysoul/p/5930361.htmlhttps://www.cnblogs.com/diysoul/p/5930372.htmlhttps://www.cnblogs.com/diysoul/p/5930388.html]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>c++</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Flask Web 学习笔记1 -- 环境]]></title>
<url>%2F2019%2F03%2F31%2Fflask-learning1%2F</url>
<content type="text"><![CDATA[-学习笔记-flask 前期准备,在目录下建立 flask 虚拟环境,开启调试模式和书写配置文档 flask = werkzeug(web 服务)+sqlalchemy(数据库)+jinja2(框架模板) flask 运行环境pip install pipenv使用 pipenv 隔离虚拟环境,防止不同项目环境冲突 命令行切换到目标目录下pipenv shell 进入虚拟环境pipenv install flask 安装 flaskpipenv graph 打印所有依赖exit 退出虚拟环境 pipenv doc python 必须重启服务器才生效 默认模板 # 从flask这个包中导入Flask这个类# Flask这个类是项目的核心,以后很多操作都是基于这个类的对象# 注册url、注册蓝图等都是基于这个类的对象__author__ = 'kevin'from flask import Flask# 创建一个Flask对象,传递__name__参数进去# __name__参数的作用:# 1. 可以规定模版和静态文件的查找路径# 2. 以后一些Flask插件,比如Flask-migrate、Flask-SQLAlchemy如果报错了,那么Flask可以通过这个参数找到具体的错误位置app = Flask(__name__)# @app.route:是一个装饰器# @app.route('/')就是将url中的/映射到hello_world这个视图函数上面# 以后你访问我这个网站的/目录的时候,会执行hello_world这个函数,然后将这个函数的返回值返回给浏览器。@app.route('/')def hello_world(): return 'Hello,World.'# 如果这个文件是作为一个主文件运行,那么就执行app.run()方法,遍历运行# 只在开发时使用if __name__ == '__main__': app.run(host='127.0.0.1',port=5000) debug 模式开启了 DEBUG 模式,那么在代码中如果抛出了异常,在浏览器的页面中可以看到具体的错误信息,以及具体的错误代码位置。方便开发者调试。 如果开启了 DEBUG 模式,那么以后在Python代码中修改了任何代码,只要按ctrl+s,flask就会自动的重新记载整个网站。不需要手动点击重新运行。 在app.run()中传递一个参数debug=True就可以开启DEBUG模式 if __name__ == '__main__': app.run(debug=True) 给app.deubg=True也可以开启debug模式。 app = Flask(__name__)app.debug = True 通过配置参数的形式设置 DEBUG 模式:app.config.update(DEBUG=True)。 # 设置配置参数的形式# DEBUG必须要大写,不能小写app = Flask(__name__)app.config.update(DEBUG=True) 通过配置文件的形式设置 DEBUG 模式:app.config.from_object(config) 导入import config使用app.config.from_object(config)新建config.py文件,写入DEBUG=true config 文件 导入import config,使用app.config.from_object(config),新建config.py文件,写入DEBUG=true app.config.from_pyfile('config.py,silence=True),新建config.py文件,写入DEBUG=true可以传递silent=True,那么这个静态文件没有找到的时候,不会抛出异常]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>flask</tag>
</tags>
</entry>
<entry>
<title><![CDATA[c++ 面向对象的一些特性]]></title>
<url>%2F2019%2F03%2F25%2Fcpp-oop%2F</url>
<content type="text"><![CDATA[-基础笔记-(loading…)C++面向对象编程知识点复习梳理,包括类、继承、重载、多态、数据抽象、数据封装、接口 类和对象类访问修饰符public公有成员在程序中类的外部是可访问的。您可以不使用任何成员函数来设置和获取公有变量的值 private私有成员变量或函数在类的外部是不可访问的,甚至是不可查看的。只有类和友元函数可以访问私有成员默认情况下,类的所有成员都是私有的一般会在私有区域定义数据,在公有区域定义相关的函数 protected保护成员在派生类(即子类)中是可访问的 构造函数,拷贝构造函数和析构函数创建、初始化和删除所创建的对象时调用构造函数的名称与类的名称是完全相同的,不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值拷贝构造函数是一种特殊的构造函数,在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。如果类带有指针变量,并有动态内存分配,则它必须有一个拷贝构造函数析构函数的名称与类的名称是完全相同的,不会返回任何值,也不能带有任何参数。析构函数有助于在跳出程序(比如关闭文件、释放内存等)前释放资源 class Classname{public: Classname(); //构造函数 Classname(const Classname &obj); //拷贝构造函数 ~Classname(); //析构函数private: int *ptr;}Classname::Classname(){ cout<<"调用构造函数"<<endl; *ptr = new int; //指针分配内存}Classname::Classname(const Classname &obj){ cout<<"调用拷贝构造函数"<<endl; *ptr = *obj.ptr; //指针分配内存}CLassname::~Classname(){ cout<<"释放内存"<<endl; delete ptr;} 一个类如果有多个字段 X、Y、Z 等需要进行初始化,可以使用如下语法 Classname::objname( double a, double b, double c): X(a), Y(b), Z(c){ ....} 浅拷贝和深拷贝浅拷贝:如果没有拷贝构造函数,编译器自动产生一个“默认拷贝构造函数”,使用“老对象”的数据成员的值对“新对象”的数据成员进行赋值当对象存在动态成员,那么浅拷贝就会出问题,在销毁对象时,两个对象的析构函数将对同一个内存空间释放两次,出现错误 深拷贝:对象中动态成员重新动态分配空间 class Classname{public: Classname(){ p = new int(100); } Classname(const Classname& r){ p = new int(100); //重新分配动态空间 *p = *(r.p); //指针分配内存 } ~Classname(){ delete p; }}; 友元函数定义在类外部,用来访问类的 private 和 protected 成员可以不使用范围解析运算符 :: 定义该函数 friend class Classname; //友元类friend void objname(); //友元函数 内联函数通过内联函数,编译器试图在调用函数的地方扩展函数体中的代码,即把该函数的代码副本放置在每个调用该函数的地方类定义中的定义的函数都是内联函数,即使没有使用 inline 说明符 this 指针每一个对象都能通过 this 指针来访问自己的地址友元函数没有 this 指针,因为友元不是类的成员 类指针一个指向 C++ 类的指针与指向结构的指针类似,访问指向类的指针的成员,需要使用成员访问运算符 ->,就像访问指向结构的指针一样。与所有的指针一样,您必须在使用指针之前,对指针进行初始化。 class Box{ public: func(){} ... private: ...};Box *ptrBox;ptrBox->func(); 静态成员变量和函数都可以被声明为静态的 声明类的成员为静态时,这意味着无论创建多少个类的对象,静态成员都只有一个副本。静态成员在类的所有对象中是共享的不能把静态成员的初始化放置在类的定义中,但是可以在类的外部通过使用范围解析运算符 :: 来重新声明静态变量从而对它进行初始化 把函数成员声明为静态的,就可以把函数与类的任何特定对象独立开来。静态成员函数即使在类对象不存在的情况下也能被调用,静态函数只要使用类名加范围解析运算符 :: 就可以访问。静态成员函数没有 this 指针,只能访问静态成员(包括静态成员变量和静态成员函数) class Box{ public: static int objectCount; static int getCount() { return objectCount; } private: ...};// 初始化类 Box 的静态成员int Box::objectCount = 0;output = Box::getCount() 存储类存储类定义 C++ 程序中变量/函数的范围(可见性)和生命周期。这些说明符放置在它们所修饰的类型之前 auto 关键字用于两种情况:声明变量时根据初始化表达式自动推断该变量的类型、声明函数时函数返回值的占位符 register(C++ 11 弃用) 存储类用于定义存储在寄存器中而不是 RAM 中的局部变量。这意味着变量的最大尺寸等于寄存器的大小(通常是一个词),且不能对它应用一元的 ‘&’ 运算符(因为它没有内存位置) static 存储类指示编译器在程序的生命周期内保持局部变量的存在,而不需要在每次它进入和离开作用域时进行创建和销毁。因此,使用 static 修饰局部变量可以在函数调用之间保持局部变量的值 extern 存储类用于提供一个全局变量的引用,全局变量对所有的程序文件都是可见的。当您使用 ‘extern’ 时,对于无法初始化的变量,会把变量名指向一个之前定义过的存储位置。 当有多个文件且定义了一个可以在其他文件中使用的全局变量或函数时,可以在其他文件中使用 extern 来得到已定义的变量或函数的引用。 mutable 说明符仅适用于类的对象,它允许对象的成员替代常量。也就是说,mutable 成员可以通过 const 成员函数修改。 thread_local 说明符声明的变量仅可在它在其上创建的线程上访问,变量在创建线程时创建,并在销毁线程时销毁。 每个线程都有其自己的变量副本。 thread_local 说明符可以与 static 或 extern 合并。 继承依据另一个类来定义一个类,这使得创建和维护一个应用程序变得更容易。这样做,也达到了重用代码功能和提高执行时间的效果。 当创建一个类时,不需要重新编写新的数据成员和成员函数,只需指定新建的类继承了一个已有的类的成员即可。这个已有的类称为基类,新建的类称为派生类。 派生类可以访问基类中所有的非私有成员。因此基类成员如果不想被派生类的成员函数访问,则应在基类中声明为 private。 class derived-class: (public/protected/private) base-class // 基类class Shape{ public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height;};// 派生类class Rectangle: public Shape{ public: int getArea() { return (width * height); }}; 多继承多继承即一个子类可以有多个父类,它继承了多个父类的特性,C++ 类可以从多个类继承成员 class <派生类名>:<继承方式1><基类名1>,<继承方式2><基类名2>,…{<派生类类体>}; // 基类 Shapeclass Shape{ public: void setWidth(int w) { width = w; } void setHeight(int h) { height = h; } protected: int width; int height;};// 基类 PaintCostclass PaintCost{ public: int getCost(int area) { return area * 70; }};// 派生类class Rectangle: public Shape, public PaintCost{ public: int getArea() { return (width * height); }}; 虚继承:解决多继承中出现的问题从不同途径继承来的同名的数据成员在内存中有不同的拷贝造成数据不一致问题,将共同基类设置为虚基类。 虚继承在创建对象的时候会创建一个虚表,从不同的路径继承过来的同名数据成员在内存中就只有一个拷贝,同一个函数名也只有一个映射。 这样不仅就解决了二义性问题,也节省了内存,避免了数据不一致的问题。 class 派生类: virtual 方式1 基类1,virtual 方式2 基类2,...{...//派生类成员声明}; class D{......};class A: virtual public D{......};class B: virtual public D{......};class C: public B, public A{.....}; 派生类无法从基类继承基类的构造函数、析构函数和拷贝构造函数基类的重载运算符基类的友元函数 重载C++ 允许在同一作用域中的某个函数和运算符指定多个定义,分别称为函数重载和运算符重载。 编译器通过把使用的参数类型与定义中的参数类型进行比较,决定选用最合适的定义。选择最合适的重载函数或重载运算符的过程,称为重载决策。 运算符重载重定义或重载大部分 C++ 内置的运算符,使用自定义类型的运算符。 重载的运算符是带有特殊名称的函数,函数名是由关键字 operator 和其后要重载的运算符符号构成的。与其他函数一样,重载运算符有一个返回类型和一个参数列表。 Box operator+(const Box& b); // 重载+运算符 函数重载同一个类中,声明几个功能类似的同名函数,但是这些同名函数的形式参数(指参数的个数、类型或者顺序)必须不同。您不能仅通过返回类型的不同来重载函数。 public:void print(int i) { cout << "整数为: " << i << endl;}void print(double f) { cout << "浮点数为: " << f << endl;}void print(char c[]) { cout << "字符串为: " << c << endl;} 多态4.2“覆盖”是指派生类函数覆盖基类函数,特征是:(1)不同的范围(分别位于派生类与基类);(2)函数名字相同;(3)参数相同;(4)基类函数必须有 virtual 关键字。 4.3“隐藏”是指派生类的函数屏蔽了与其同名的基类函数,特征是: (1)如果派生类的函数与基类的函数同名,但是参数不同,此时,不论有无 virtual 关键字,基类的函数将被隐藏(注意别与重载混淆)。(2)如果派生类的函数与基类的函数同名,但是参数相同,但是基类函数没有 virtual 关键字。此时,基类的函数被隐藏(注意别与覆盖混淆)。 数据抽象数据封装接口 参考资料:http://c.biancheng.net/cplus/w3school]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>c++</tag>
</tags>
</entry>
<entry>
<title><![CDATA[基于二叉树的衍生算法]]></title>
<url>%2F2019%2F03%2F24%2Fbintree2%2F</url>
<content type="text"><![CDATA[二叉树衍生算法 loading… 并查集堆哈夫曼树]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[二叉树的相关操作]]></title>
<url>%2F2019%2F03%2F24%2Fbintree%2F</url>
<content type="text"><![CDATA[二叉树的笔记 loading… 存储结构基本操作创建插入查找四种遍历方法二叉树静态实现二叉查找树平衡二叉树一般意义上的树深度优先搜索广度优先搜索]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[二分查找策略]]></title>
<url>%2F2019%2F03%2F21%2Ftwo-divide%2F</url>
<content type="text"><![CDATA[需要一个严格单调的序列,就能将 O(n)的复杂度降到 O(logn)的优秀算法非常适合有序数列的查找二分的思想也可以用来逼近准确值和降幂求值 二分查找思路设 left,right,mid,查找数 x查找的数 > mid,left = mid + 1查找的数 < mid,right = mid - 1直到查找的数 = mid,程序结束 #include<cstdio>int binSearch(int array[], int left, int right, int x){ int mid; while(left<=right) { mid = (left + right) / 2; if(array[mid] == x) return mid; else if(array[mid] > x) right = mid - 1; else left = mid + 1; } return false; //查找失败则返回false}int main(){ const int n = 10; //序列元素个数 int array[n] = {1,2,3,4,5,6,7,8,9,10}; int result = binSearch(array,0,n-1,6); printf("%d",result); return 0;} mid = (left + right) / 2 可能会导致 int 类型溢出,可以改成 mid = left + (right - left) / 2 当序列中有相同的元素求解序列中第一个等于 x 的元素和最后一个等于 x 的元素 int lower_bound(int array[], int left, int right, int x){ int mid; while(left < right) { mid = (left + right) / 2; if(array[mid] >= x) right = mid; else left = mid + 1; } return left; // left==right 循环停止} int upper_bound(int array[], int left, int right, int x){ int mid; while(left < right) { mid = (left + right) / 2; if(array[mid] > x) right = mid; else left = mid + 1; } return left; // left==right 循环停止} 逼近无理数近似值计算 f(x)中 x 的值 const double eps = 1e-5;double func(double x){ return ...; // f(x)的公式}double solve(double L, double R){ double left = L, right = R, mid; while(right - left > eps) { mid = (left + right) / 2; if(func(mid)>0) right = mid; else left = mid } return mid;} 快速求幂二分幂的思想可以用来降低时间复杂度若 b 为奇数,a^b = a a^b-1若 b 为偶数,a^b = a^b/2 a^b/2直到 a^0 =1,依次退回计算 快速幂递归写法求解 a^b%m 的递归写法 typedef long long LL;LL binFunc(LL a, LL b, LL m){ if(b == 0) return 1; // a^0 == 1 if(b % 2 ==1) return a* binFunc(a, b-1, m) % m; else { LL mul = binFunc(a, b/2, m); return mul * mul % m; }} b % 2 ==1可以写成b&1,将 b 和 1 进行按位与操作,判断 b 末尾是否为 1 快速幂非递归写法将 b 写成若干 2 次幂之和,将 a^b 表示成若干项乘积 typedef long long LL;LL binFunc(LL a, LL b, LL m){ LL ans = 1; while(b>0) { if(b&1) ans = ans * a % m; //判断2进制末尾是否为1,是的话*a a = a * a % m; b >>= 1; } return ans;}]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[分治和递归基础算法]]></title>
<url>%2F2019%2F03%2F21%2Fdivide%2F</url>
<content type="text"><![CDATA[写分治和贪心时,习惯性地会去思索程序的全局,而一旦展开去想,基本上就大脑溢出了目前还是无法把握递归式和递归边界,这算法终将是一生之敌。 Fibonacci用 Fibonacci 数列简单熟悉一下算法 #include<cstdio>int Fibonacci(int n){ if(n==0 | n==1) return 1; //递归边界 else return Fibonacci(n-1) + Fibonacci(n-2); //递归式}int main(){ int n; scanf("%d",&n); printf("%d",Fibonacci(n)); return 0;} 全排列按照字典顺序从小到大顺序输出 1-n 全排列 思路:数组 P 存放当前排列,hashTable 置为 true 存放已在 P 中的数字递归式:P 按位处理,数字 x 不在 P 中,将 x 填入 P,P 处理下一位递归边界:处理完 n 位,输出排列,hashTable[x]=false 还原 #include<cstdio>const int maxn = 1024;int P[maxn],hashTable[maxn] = {false},n;//处理第index位void generateP(int index){ if(index == n+1) //到达递归边界 { for(int i=0; i<n; i++) printf("%d ",P[i]); } printf("\n"); return; else { for(int x=1; x<=n; x++) { if(hashTable[x] == false) //递归式逻辑 { P[index] = x; hashTable[x] = true; generateP(index+1); hashTable[x] = false; } } }}int main(){ scanf("%d",&n); //输入有几个数 generateP(1); //从1开始递归 return 0;} n 皇后问题皇后两两不在同行同列同对角线 思路:到达递归边界时,遍历任意两个皇后查看是否满足条件递归边界:列 index 到达 n,满足八皇后条件,count+1递归式:行 x 不在 hashTable 中,此列放置皇后,index 移动到下一列 int count = 0;void generateP(int index){ bool flag = true; if(index == n+1) //到达递归边界,判断是否合法 { for(int i=1; i<=n; i++) for(int j=i+1; j<=n; j++) if(abs(P[i]-P[j]) == abs(i-j)) flag = false; if(flag) count++; return; } else { for(int x=1; x<=n; x++) { if(hashTable[x] == false) //递归式 { P[index] = x; hashTable[x] = true; generateP(index+1); hashTable[x] = false; } } }} 枚举所有情况会比较耗时间,可以在放置皇后的同时遍历之前的,判断是否有冲突 int count = 0;void generateP(int index){ if(inedx == n+1) //到达递归边界 count++; return; else { for(int x=1; x<=n; x++) { if(hashTable[x] == false) { bool flag = true; for(int pre=1; pre<index; pre++) { if(abs(P[index]-P[pre]) == abs(index-pre)) { flag == false; break; } } if(flag) { P[index] = x; hashTable[x] = true; generateP(index+1); hashTable[x] = false; } } } }}]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[cpp_stl]]></title>
<url>%2F2019%2F03%2F20%2Fcpp-stl%2F</url>
<content type="text"><![CDATA[C++ STL 接触(loading…)在学习 C++,数据结构基础上,STL 是基础和进阶的分水岭,要多尝试用 STL 实现常用的算法和数据结构 Template(模板)模板(Template)指 C++程序设计设计语言中采用类型作为参数的程序设计,支持通用程序设计。C++ 的标准库提供许多有用的函数大多结合了模板的观念,如 STL 以及 IO Stream。 函数模板可以实现不同类型的函数代码的复用 // 模板定义template<typename t> swap(t &t1, t &t2){ t tmpT; tmpT = t1; t1 = t2; t2 = tmpT;}//模板实例化int main(){ int num1 = 1, num2 = 2; float num3 = 1.0, num4 = 2.0; swap<int>(num1, num2); swap<float>(num3, num4); return 0;} 类模板可以实现不同类型的类的复用 // 模板定义template<class t> class Stack{ public: Stack(){ maxSize = 100; size = 0; p = new t[maxSize]; }; ~Stack(){ delete p[]; p = nullptr; }; void push(t num){ size++; p[size-1] = num; }; t pop(){ t num = p[size-1]; size--; return num; }; bool isEmpty(){ return size == 0; }; private: t *p; int maxSize; int size;}// 模板实例化int main(){ Stack<int> intStack; Stack<float> floatStack; ... intStack.push(1); intStack.push(2); intStack.push(3); ... while(!intStack.isEmpty()){ printf("%d",intStack.pop()); } return 0;} 模板参数模板可以有常规的类型参数,也可以有默认模板参数template<class t, int maxSize = 100> class stack{} 一个类没有模板参数,但是成员函数有模板参数,是可行的 有些特殊的参数可以使用模板专门化template<> void swap(std::vector<int>& t1, std::vector<int>& t2){} string 类使用指针 ++ 和 — 操作符来遍历字符串,无论 ASCII 码字符串还是 Unicode 字符串,使用指针均能够正确无误地返回要寻求的字符位置。使用数组处理字符串中的字符也非常方便。 STL 中只有一个字符串类,即 basic_string。类 basic_string 实现管理以 \0 结尾的字符数组,字符类型由模板参数决定。basic_string 有两个预定义类型:包含 char 的 string 类型和包含 wchar 的 wstring 类型。 string 作为类出现,其集成的操作函数足以完成多数情况下的需要。可以使用 “=” 进行赋值,使用 “==” 进行等值比较,使用 “+” 做串联。 string 类包含了 6 个构造函数。string 类支持 cin 方式和 getline() 方式两种输入方式。 basic_stringbasic_string 是一个类模板,包括 string,wstring,u16stirng 和 u32stringtypedef basic_string <char> string;typedef basic_string <wchar> wstring; //wstring 类是为了便于使用宽字符集,例如 Unicode 或某些欧洲字符集 string 函数string 类提供的各种操作函数大致分为八类:构造器和析构器、大小和容量、元素存取、字 符串比较、字符串修改、字符串接合、I/O 操作以及搜索和查找。 函数名称 功能 构造函数 产生或复制字符串 析构函数 销毁字符串 =,assign 赋以新值 Swap 交换两个字符串的内容 + =,append( ),push_back() 添加字符 insert () 插入字符 erase() 删除字符 clear () 移除全部字符 resize () 改变字符数量 replace() 替换字符 + 串联字符串 ==,! =,<,<=,>,>=,compare() 比较字符串内容 size(),length() 返回字符数量 max_size () 返回字符的最大可能个数 empty () 判断字符串是否为空 capacity () 返回重新分配之前的字符容量 reserve() 保留内存以存储一定数量的字符 [ ],at() 获取字符串元素 >>,getline() 从 stream 中读取某值 << 将值写入 stream copy() 将内容复制为一个 C - string c_str() 将内容以 C - string 形式返回 data() 将内容以字符数组形式返回 substr() 返回子字符串 find() 搜寻某子字符串或字符 rfind() 逆向搜寻字符串或字符 find_first_of()**find_last_of()** 搜寻第一个/最后一个匹配的字符串 begin( ),end() 提供正向迭代器支持 rbegin(),rend() 提供逆向迭代器支持 get_allocator() 返回配置器 string 构造和析构函数 类构造函数 string strs //生成空字符串string s(str) //生成字符串str的复制品string s(str, stridx) //将字符串str中始于stridx的部分作为构造函数的初值string s(str, strbegin, strlen) //将字符串str中始于strbegin、长度为strlen的部分作为字符串初值string s(cstr) //以C_string类型cstr作为字符串s的初值string s(cstr,char_len) //以C_string类型cstr的前char_len个字符串作为字符串s的初值string s(num, c) //生成一个字符串,包含num个c字符string s(strs, beg, end) //以区间[beg, end]内的字符作为字符串s的初值 析构函数~string() //销毁所有内存,释放内存 5 种序列容器序列容器以线性序列的方式存储元素。它没有对元素进行排序,元素的顺序和存储它们的顺序相同。 array<T,N> (数组容器) :是一个长度固定的序列,有 N 个 T 类型的对象,不能增加或删除元素。 vector<T> (向量容器) :是一个长度可变的序列,用来存放 T 类型的对象。必要时,可以自动增加容量,但只能在序列的末尾高效地增加或删除元素。 deque<T> (双向队列容器) :是一个长度可变的、可以自动增长的序列,在序列的两端都不能高效地增加或删除元素。 list<T> (链表容器) 是一个长度可变的、由 T 类型对象组成的序列,它以双向链表的形式组织元素,在这个序列的任何地方都可以高效地增加或删除元素。访问容器中任意元素的速度要比前三种容器慢,这是因为 list<T> 必须从第一个元素或最后一个元素开始访问,需要沿着链表移动,直到到达想要的元素。 forward list<T> (正向链表容器) :是一个长度可变的、由 T 类型对象组成的序列,它以单链表的形式组织元素,是一类比链表容器快、更节省内存的容器,但是它内部的元素只能从第一个元素开始访问。 常用函数成员函数成员 array vector dequebegin() - 返回幵始迭代器 是 是 是end() - 返回结束迭代器 是 是 是rbegin() - 返回反向’开始迭代器 是 是 是rend() - 返回反向结束迭代器 是 是 是cbegin() - 返 M const 开始迭代器 是 是 是cend() - 返回 const 结束迭代器 是 是 是crbegin() - 返回 const 反向开始迭代器 是 是 是crend() - 返回 const 反向结束迭代器 是 是 是assign() - 用新元素替换原有内容 - 是 是operator=() - 复制同类型容器的元素,或者用初始化列表替换 现有内容 是 是 是size() - 返回实际元素个数 是 是 是max_size() - 返回元素个数的设大值 是 是 是capacity() - 返回当前容量 - 是 -empty() - 返回 true,如果容器中没有元素的话 是 是 是resize() - 改变实际元素的个数 - 是 是shrink _to_fit() - 将内存减少到等于当前元素实际所使用的大小 - 是 是front() - 返回第一个元素的引用 是 是 是back() - 返回铖后一个元素的引用 是 是 是operator - 使用索弓丨访问元素 是 是 是at() - 使用经过边界检査的索引访问元素 是 是 是push_back() - 在序列的尾部添加一个元素 - 是 是insert() - 在指定的位置插入一个或多个元素 - 是 是emplace() - 在指定的位置直接生成一个元素 - 是 是emplace_back() - 在序列尾部生成一个元素 - 是 是pop_back() - 移出序列尾部的元素 - 是 是erase() - 移出一个元素或一段元素 - 是 是clear() - 移出所苻的元素,容器大小变为 0 - 是 是swap() - 交换两个容器的所有元素 是 是 是data() - 返回包含元素的内部数组的指针 是 是 - 函数成员 list forward listbegin() - 返回开始迭代器 是 是end() - 返回结束迭代器 是 是rbegin() - 返回反向开始迭代器 是 -rend() - 返回反向结束迭代器 是 -cbegin() - 返回 const 开始结束迭代器 是 是before_begin() - 返回一个指向第一个元素前一个位置的迭代器 - 是cbefore_begin() - 返回一个指向第一个元素前一个位置的 const 迭代器 - 是cend() - 返回 const 结束迭代器 是 是crbegin() - 返回 const 反向开始迭代器 是 -crend() - 返回 const 反向结束迭代器 是 -assign() - 用新元素替换原有内容 是 是operator=() - 复制同类型容器的元素,或者用初始化列表替换现有内容 是 是size() - 返回实际元素个数 是 -max_size() - 返回元素个数的最大值 是 是resize() - 改变实际元素的个数 是 是empty() - 返回 true,如果容器中没有元素的话 是 是from() - 返回第一个元素的引用 是 是back() - 返回最后一个元素的引用 是 -push_back() - 在序列的潘部添加一个元素 是 -push_front() - 在序列的起始位置添加一个元素 是 是emplace() - 在指矩位置直接生成一个元素 是 -emplace_after() - 在指定位置的后面直接生成一个元素 - 是emplace_back() - 在序列尾部生成一个元素 是 -cmplacc_front() - 在序列的起始位生成一个元索 是 是insert() - 在指定的位置插入一个或多个元素 是 -insert_after() - 在指定位置的后面插入一个或多个元素 - 是pop_back() - 移除序列尾部的元素 是 -pop_front() - 移除序列头部的元素 是 是reverse()-反向元素的顺序 是 是erase() - 移除指定位置的一个元素或一段元素 是 -erase_after() - 移除指定位 1;后面的一个元素或一段元素 - 是remove() - 移除所苻和参数匹配的元素 是 是remove_if() - 移除满足一元函数条件的所有元素 是 是unique() - 移除所有连续重复的元素 是 是clear() - 移除所有的元素,容器大小变为 0 是 是swap() - 交换两个容器的所有元素 是 是sort() - 对元素进行排序 是 是merge() - 合并两个有序容器 是 是splice() - 移动指定位置前面的所有元素到另一个同类型的 list 中 是 -splice_after() - 移动指定位置后面的所有元素到另一个同类型的 list 中 - 是 具体使用array:std::array<typename, 100> data {}; 通过调用数组对象的成员函数 fill(),可以将所有元素设成给定值 data.fill(0.0); 获取元素 data[num] 为了获取时能够检查越界索引值,可以使用成员函数 at(),当传给 at() 的索引是一个越界值时,这时会抛出 std::out_of_rang 异常 data.at(num) vector:std::vector<typename> values(num) {1,2,3,...}; 通过调用 reserve() 来增加容器的容量 values.reserve(20) 通过调用成员函数 resize() 可以改变容器大小 values.resize(size, num) 使用 push_back()、insert()、emplace() 或 emplace_back() 函数来添加一个元素values.push_back() //使用时会调用构造函数和拷贝构造函数values.emplace_back() // 不需要触发构造函数和拷贝构造函数 front() 和 back() 分別返回序列中第一个和最后一个元素的引用 values.front() data() 返回指向数组的指针 values.data() 迭代器 迭代器auto first = std::begin(data);auto last = std::end (data); 3 种容器适配器容器适配器是一个封装了序列容器的类模板,它在一般序列容器的基础上提供了一些不同的功能。 stack<T>:是一个封装了 deque<T> 容器的适配器类模板,默认实现的是一个后入先出(Last-In-First-Out,LIFO)的压入栈。stack<T>· 模板定义在头文件 stack 中。 queue<T>:是一个封装了 deque<T> 容器的适配器类模板,默认实现的是一个先入先出(First-In-First-Out,LIFO)的队列。可以为它指定一个符合确定条件的基础容器。queue<T> 模板定义在头文件 queue 中。 priority_queue<T>:是一个封装了 vector<T> 容器的适配器类模板,默认实现的是一个会对元素排序,从而保证最大元素总在队列最前面的队列。priority_queue<T> 模板定义在头文件 queue 中。 4 种 map 容器map<K,T>容器,保存的是 pair<const K,T> 类型的元素。pair<const K,T> 封装了一对键对象,键的类型是 K,对象的类型是 T。每个键都是唯一的,所以不允许有重复的键;但可以保存重复的对象,只要它们的键不同。map 容器中的元素都是有序的,元素在容器内的顺序是通过比较键确定的。默认使用 less 对象比较。multimap 容器和 map 容器类似,也会对元素排序。它的键必须是可比较的,元素的顺序是通过比较键确定的。和 map 不同的是,multimap 允许使用重复的键。因此,一个 multimap 容器可以保存多个具有相同键值的 元素。unordered_map 中 pair< const K,T>元素的顺序并不是直接由键值确定的,而是由键值的哈希值决定的。哈希值是由一个叫作哈希的过程生成的整数,本章后面会解释这一点。unordered_map不允许有重复的键。unordered_multimap 也可以通过键值生成的哈希值来确定对象的位置,但它允许有重复的键。 set 容器set 容器是关联容器,其中的对象是对象它们自己的键 随机数流迭代器数值、时间和复数C++常用算法和 algorithm 库 参考资料C 语言中文网C++ Primer Plus 第 6 版中文版学校教材]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>c++</tag>
</tags>
</entry>
<entry>
<title><![CDATA[散列表基础算法]]></title>
<url>%2F2019%2F03%2F19%2Fhashtable%2F</url>
<content type="text"><![CDATA[-散列基础-散列(hash)是常用的算法思想之一,它使用空间换时间的思想在我第一次碰到时就感觉巧妙如魔法一般。特别是在进行一些大量数字和字符串比较方面,hash 能瞬间将 O(n^2)的复杂度降到 O(n),单次查询的复杂度降到 O(1),靠的就是数组下标与查询的元素之间建立的唯一转换关系。 常用 hash线性变换函数:H(key) = a*key+b除留余数:h(key) = key%mod 除留余数法会出现冲突的情况,需要解决多个 hash 值相同的情况 线性探测法:从当前位置检查相邻地址是否被占用,如果都被占用,循环检查下一个位置 平方探测法:从当前位置检查+1,-1,+4,-4,+9,-9……如果检查中+k^2 超过表长(Tablesize),[H(key)+k^2]%Tablesize 链地址法:把 hash 相同的 key 连接成单链表 整数 hash查询数组 M 中的数在数组 N 中是否出现过常规思路:遍历所有 N,要遍历 M 次,时间复杂度 O(MN)hash 思路:bool hashTable[maxn]={false},先读入 N,N 中出现的数 x,hashTable[x]=true,再查询 M,时间复杂度 O(M+N) 示例 #include<cstdio>const int maxn = 1024;bool hashTable[maxn] = {false};int main(){ int n[10] = {2,6,8,12,23,5,15,5,0,1}; int m[3] = {8,22,5}; int x; for(int i=0; i<10; i++) hashTable{n[i]} = true; for(int j=0; j<3;j++) { if(hashTable{m[j]]} == true) printf("%d,yes\n",m[j]); else printf("%d,no\n",m[j]); } return 0;} 查询 M 中的数在 N 中出现的次数将 hashTable 替换为 int 类型进行计数 示例 #include<cstdio>const int maxn = 1024;int hashTable[maxn] = {0};int main(){ int n[10] = {2,6,8,12,8,5,15,5,0,1}; int m[3] = {8,12,5}; int x; for(int i=0; i<10; i++) hashTable{n[i]}++; for(int j=0; j<3;j++) { printf("%d\n",hashTable{m[j]}); } return 0;} 字符串 hash需要将字符串和整数唯一对应,可以直接对应或使用 hash 函数对应:A-Z 0~25,a-z 26~51 //将字符串S转换为整数int hashFunc(char S[], int len){ int hashID = 0; for(int i=0; i<len; i++) { if(S[i]>='A' && S[i]<='Z') hashID = hashID*52 + S[i] - 'A'; else if(S[i]>='a' && S[i]<='z') hashID = hashID*52 + S[i]-'a'+ 26; } return id;}int id = hashFunc(P[i],52);hashTable[id] = P[i]; 查询 N 个字符串中 M 个字符串出现的次数,每个字符串长度固定为 5#include<cstdio>const int maxn = 100;char S[maxn][5],temp[5];int hashTable[26*26*26+10];//每个字符串拥有唯一idint hashFunc(char S[], int len){ int id = 0; for(int i=0; i<len; i++) { id = id*26 + (S[i]-'A'); } return id;}int main(){ int n, m; scanf("%d%d", &n, &m); for(int i=0; i<n; i++) { sacnf("%s", S[i]); int id = hashFunc(s[i], 3); hashTable[id]++; } for(int i=0; i<m; i++) { sacnf("%s",temp); int id = hashFunc(temp, 3); printf("%d",hashTable[id]); } return 0;}]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Autonomous Vehicles translate -- datasets & bechmarks]]></title>
<url>%2F2019%2F03%2F18%2Fdatasets-benchmarks%2F</url>
<content type="text"><![CDATA[Computer Vision for Autonomous Vehicles:Problems, Datasets and State-of-the-Art自动驾驶技术的计算机视觉:问题,数据和前沿技术数据集和基准 datasets & Benchmarks 数据集和基准 Datasets have played a key role in the progress of many research fields by providing problem specific examples with ground truth. They allow quantitative evaluation of approaches providing key insights about their capacities and limitations. |In particular, several of these datasets Geiger et al. (2012b); Scharstein & Szeliski (2002); Baker et al. (2011); Everingham et al. (2010); Cordts et al. (2016) also provide online evaluation servers which allow for a fair comparison on held-out test sets and provide researchers in the field an up-to-date overview over the state-of-the-art. |This way, current progress and remaining challenges can be easily identified by the research community. In the context of autonomous vehicles, the KITTI dataset Geiger et al. (2012b) and the Cityscapes dataset Cordts et al.(2016) have introduced challenging benchmarks for reconstruction, motion estimation and recognition tasks, and contributed to closing the gap between laboratory settings and challenging real-world situations. |Only a few years ago, datasets with a few hundred annotated examples were considered sufficient for many problems. The introduction of datasets with many hundred to thousands of labeled examples, however, has led to spectacular breakthroughs in many computer vision disciplines by training high-capacity deep models in a supervised fashion. |However, collecting a large amount of annotated data is not an easy endeavor, in particular for tasks such as optical flow or semantic segmentation. This initiated a collective effort to produce that kind of data in several areas by searching for ways to automate the process as much as possible such as through semi-supervised learning or synthesization. 数据集在许多研究领域进展方面发挥了关键作用,提供了真实的(ground truth)问题特例。它们允许通过提供有关其能力与局限的核心信息,数据集还可以对方法进行量化评估。 特别地,这些数据集中的几个比如 Geiger(2012b);Scharstein&Szeliski(2002); Baker(2011);Everinghamet al(2010); Cordts(2016)也提供在线评估服务器允许在延期测试(held-out)中进行公平的比较,而且为该领域的研究人员提供更新的目前最好的算法。 这种方式可以让研究团队很容易地确定目前的进展和剩下的挑战。在自主车辆的环境中,KITTI 数据集 Geiger(2012b)和 Cityscapes 数据集 Cordts (2016)为重建、运动估计和识别任务引入了挑战性的基准,因此缩小了实验室设置与挑战现实世界的情况之间的差距。 几年前,有数百个注释例子的数据集对于解决很多问题是足够的。然而,有数百到数千个有标签的例子的数据集的引入,通过以监督的方式训练大容量深度模型,已经使得许多计算机视觉学科的重大突破。 然而,收集大量的注释数据不是一个容易的事情,特别是对于诸如光流或者语义分割的任务。这使得集体努力通过搜索尽可能多的方式来自动化过程,例如通过半监督学习或合成,从而在多个领域产生了这种数据。 Real-World Datasets 真实数据集 While several algorithmic aspects can be inspected using synthetic data, real-world datasets are necessary to guarantee performance of algorithms in real situations. For example, algorithms employed in practice need to handle complex objects and environments while facing challenging environmental conditions such as direct lighting, reflections from specular surfaces, fog or rain. The acquisition of ground truth is often labor intensive because very often this kind of information cannot be directly obtained with a sensor but requires tedious manual annotation. |For example, (Scharstein & Szeliski (2002),Baker et al. (2011)) acquire dense pixel-level annotations in a controlled lab environment whereas Geiger et al. (2012b); Kondermann et al. (2016) provide sparse pixel-level annotations of real street scenes using a LiDAR laser scanner. Recently, crowdsourcing with Amazon’s Mechanical Turk9 have become very popular to create annotations for large scale datasets, e.g., Deng et al. (2009); Lin et al. (2014); Leal-Taix´e et al. (2015); Milan et al. (2016). However, the annotation quality obtained via Mechanical Turk is often not sufficient to be considered as reference and significant efforts in post-processing and cleaning-up the obtained labels is typically required. |In the following, we will first discuss the most popular computer vision datasets and benchmarks addressing tasks relevant to autonomous vision. Thereafter, we will focus on datasets particularly dedicated to autonomous vehicle applications. 虽然可以使用合成数据检查几个算法方面,但实际数据集对于确保算法在实际情况下的性能是必要的。例如,在实践中使用的算法需要处理复杂的对象和环境,同时面对挑战性的环境条件,例如直接照明,镜面反射,雾或雨。获取 ground truth 通常是劳动密集型的,因为这种信息通常不能用传感器直接获得,而是需要繁琐的手动注释。 例如,(Scharstein&Szeliski(2002),Baker(2011))在受控实验室环境中获得了密集的像素级注释,而 Geiger 等人(2012B); Kondermann 等人(2016)使用 LiDAR 激光扫描仪提供实际街景场景的稀疏像素级注解。 最近,亚马逊的 Mechanical Turk 的众包已经变得非常受欢迎,为大型数据集创建注释,例如 Deng(2009);Lin(2014); Leal-Taix’e(2015); Milan(2016)。然而,通过 Mechanical Turk 获得的注释质量通常不太合适被认为是参考,并且通常需要在后处理中最初的重大努力和清理所获得的标签中也是非常需要的。 在下文中,我们将首先讨论最流行的计算机视觉数据集和基准,以解决与自主视觉相关的任务。此后,我们将专注于数据集,尤其致力于自动驾驶车辆的应用。 Stereo and 3D Reconstruction: The Middlebury stereo benchmark introduced by Scharstein & Szeliski (2002) provides several multi-frame stereo data sets for comparing the performance of stereo matching algorithms. |Pixel-level ground truth is obtained by hand labeling and reconstructing planar components in piecewise planar scenes. Scharstein & Szeliski (2002) further provide a taxonomy of stereo algorithms that allows the comparison of design decisions and a test bed for quantitative evaluation. |Approaches submitted to their benchmark website are evaluated using the root mean squared error and the percentage of bad pixels between the estimated and ground truth disparity maps. Scharstein & Szeliski (2003) and Scharstein et al. (2014) introduced novel datasets to the Middlebury benchmark comprising more complex scenes and including ordinary objects like chairs, tables and plants. In both works a structured lighting system was used to create ground truth. |For the latest version Middlebury v3, Scharstein et al. (2014) generate highly accurate ground truth for high-resolution stereo images with a novel technique for 2D subpixel correspondence search and self-calibration of cameras as well as projectors. This new version achieves significantly higher disparity and rectification accuracy than those of existing datasets and allows a more precise evaluation. An example depth map from the dataset is illustrated in Figure 1. The Middlebury multi-view stereo (MVS) benchmark11 by Seitz et al. (2006) is a calibrated multi-view image dataset with registered ground truth 3D models for the comparison of MVS approaches. The benchmark played a key role in the advances of MVS approaches but is relatively small in size with only two scenes. |In contrast, the TUD MVS dataset12 by Jensen et al. (2014) provides 124 different scenes that were also recorded in controlled laboratory environment. Reference data is obtained by combining structured light scans from each camera position and the resulting scans are very dense, each containing 13.4 million points on average. For 44 scenes the full 360 degree model was obtained by rotation and scanning four times with 90 degree intervals. In contrast to the datasets so far, Sch¨ops et al. (2017) provide scenes that are not carefully staged in a controlled laboratory environment and thus represent real world challenges. Sch¨ops et al. (2017) recorded high-resolution DSLR imagery as well as synchronized low-resolution stereo videos in a variety of indoor and outdoor scenes. A high-precision laser scanner allows to register all images with a robust method. The high-resolution images enable the evaluation of detailed 3D reconstruction while the low-resolution stereo images are provided to compare approaches for mobile devices. 立体与 3D 重建类数据集:由 Scharstein&Szeliski(2002)引入的 Middlebury 立体声基准测试仪提供了多个立体声数据集,用于比较立体匹配算法的性能。 通过在分段平面场景中手工标记和重建平面构成获得像素级地面真值。Scharstein 和 Szeliski(2002)进一步提供立体声算法的分类法,允许通过比较设计决策和测试台来进行定量评估。 使用均方误差以及估计值和地面真实视差图之间坏像素的百分比来评估提交给其基准网站的方法。 Scharstein & Szeliski (2003) 和 Scharstein et al. (2014)为 Middlebury 基准引入了一种新颖的数据集,这个数据及包含更多复杂的场景和普通的物体,比如椅子、桌子、植物等对象。在这两个工作中,均使用一个结构化的照明系统来创造地面实况。 对于最新版本的 Middlebury v3,Scharstein(2014)采用新颖的 2D 子像素对应搜索和相机自动校准技术以及投影机为高分辨率立体图像生成高精度的地面实况。与现有数据集相比,该新版本的差异和整改精度明显提高,可以进行更精确的评估。 Figure 1 是来自数据集的示例深度图:Seitz 等人的 Middlebury 多视点立体声(MVS)基准测试(2006)是注册地面真相 3D 模型用于比较 MVS 方法一种校准的多视图图像数据集。基准测试在 MVS 方法的进步中发挥了关键作用,但只有两个场景,尺寸相对较小。相比之下,Jensen 等人的 TUD MVS 数据集(2014 年)提供了 124 个不同的场景,这些场景也被记录在受控实验室环境中。 参考数据通过组合来自每个摄像机位置的结构光扫描获得,并且所得到的扫描非常密集,平均每个包含 13.4million 个点。对于 44 个场景,通过以 90 度的间隔旋转和扫描四次获得完整的 360 度模型。 与迄今为止的数据集相比,Sch¨ops 等人(2017 年)提供了在受控实验室环境中未仔细分级的场景,从而代表了现实世界的挑战。Sch¨ops et al. (2017) 录制了高分辨率 DSLR 单反相机图像以及各种室内和室外场景中同步的低分辨率立体视频。 高精度激光扫描仪允许以强大的方法注册所有图像。高分辨率图像可以评估详细的 3D 重建,同时提供低分辨率立体图像来比较移动设备的方法。 Optical Flow: The Middlebury flow benchmark13 by Baker et al. (2011) provides sequences with non-rigid motion, synthetic sequences and a subset of the Middlebury stereo benchmark sequences (static scenes) for the evaluation of optical flow methods. For all non-rigid sequences, ground truth flow is obtained by tracking hidden fluorescent textures sprayed onto the objects using a toothbrush. The dataset comprises eight different sequences with eight frames each. Ground truth is provided for one pair of frames per sequence. Besides the limited size, real world challenges like complex structures, lighting variation and shadows are missing as the dataset necessitates laboratory conditions which allow for manipulating the light source between individual captures. In addition, it only comprises very small motions of up to twelve pixels which do not admit the investigation of challenges provided by fast motions. Compared to other datasets, however, the Middlebury dataset allows to evaluate sub-pixel precision since it provides very accurate and dense ground truth. Performance is measured using the angular error (AEE) and the absolute end point error (EPE) between the estimated flow and the ground truth. Janai et al. (2017) present a novel optical flow dataset comprising of complex real world scenes in contrast to the laboratory setting in Middlebury. High-speed video cameras are used to create accurate reference data by tracking pixel through densely sampled space-time volumes. This method allows to acquire optical flow ground truth in challenging everyday scenes in an automatic fashion and to augment realistic effects such as motion blur to compare methods in varying conditions. Janai et al. (2017) provide 160 diverse real-world sequences of dynamic scenes with a significantly larger resolution (1280X1024 Pixels) than previous optical datasets and compare several state of-the-art optical techniques on this data. 光流类数据集:Baker 等人的“Middlebury 流量标准” (2011)提供了具有非刚性运动序列,合成序列和 Middlebury 立体声基准序列(静态场景)的子集的序列,用于评估光流方法。 对于所有非刚性序列,通过使用 toothbrush 牙刷追踪在物体上喷洒的隐藏的荧光纹理来获得地面真实流。 数据集包含八个不同的序列,每个序列具有八个帧。 每个序列提供一对帧的地面实况。除了有限的大小之外,由于数据集需要实验室条件,允许在各个捕获之间操纵光源,所以缺少像复杂结构,照明变化和阴影这样的真实世界挑战。 此外,它只包含最多十二个像素的非常小的运动,不承认对快速运动提供的挑战的调查。 然而,与其他数据集相比,Middlebury 数据集可以评估子像素精度,因为它提供了非常精确和密集的地面实例。 使用角度误差(AEE)和估计流量与地面实数之间的绝对终点误差(EPE)来测量性能。Janai 等人 (2017)提出了一个新颖的光流数据集,其中包括复杂的现实世界场景,与 Middlebury 的实验室设置相反。 高速视频摄像机用于通过密集采样的时空容量跟踪像素来创建精确的参考数据。 该方法允许以自动方式在挑战性的日常场景中获取光流场地真相,并且增加诸如运动模糊的现实效果以在不同条件下比较方法。 Janai 等人 (2017 年)提供了 160 个不同的现实世界动态场景序列,具有比以前的光学数据集显着更大的分辨率(1280x1024 像素),并比较了这些数据的几种最先进的光学技术。 Object Recognition and Segmentation: The availability of large-scale, publicly available datasets such as ImageNet (Denget al. (2009)), PASCAL VOC (Everingham et al. (2010)), Microsoft COCO (Lin et al.(2014)), Cityscapes (Cordts et al.(2016)) and TorontoCity (Wang et al. (2016)) have had a major impact on the success of deep learning in object classification, detection, and semantic segmentation tasks. The PASCAL Visual Object Classes (VOC) challenge14 by Everingham et al. (2010) is a benchmark for object classification, object detection, object segmentation and action recognition. It consists of challenging consumer photographs collected from Flickr with high quality annotations and contains large variability in pose, illumination and occlusion. Since its introduction, the VOC challenge has been very popular and was yearly updated and adapted to the needs of the community until the end of the program in 2012. Whereas the first challenge in 2005 had only 4 different classes, 20 di erent object classeswere introduced in 2007. Over the years, the benchmark grew in size reaching a total of 11,530 images with 27,450 ROI annotated objects in 2012. In 2014, Lin et al. (2014) introduced the Microsoft COCO dataset15 for the object detection, instance segmentation and contextual reasoning. They provide images of complex everyday scenes containing common objects in their natural context. The dataset comprises 91 object classes, 2.5 million annotated instances and 328k images in total. Microsoft COCO is significantly larger in the number of instances per class than the PASCAL VOC object segmentation benchmark. All objects are annotated with per-instance segmentations in an extensive crowd worker effort. Similar to PASCAL VOC, the intersection-overunion metric is used for evaluation. 对象识别与分割类数据集:大量的公开数据集,如 ImageNet(Deng 等人(2009)),PASCAL VOC(Everingham 等(2010)),Microsoft COCO(Lin 等人(2014)),Cityscapes(Cordts (2016))和 TorontoCity(Wang 等人(2016 年))对物体分类,目标检测和语义分割任务中深入学习的成功产生了重大影响。 由 Everingham 等人(2010)提供的 PASCAL 视觉对象类(VOC)挑战是对象分类,物体检测,物体分割和动作识别的基准。它由具有高质量标注的 Flickr 收集的有挑战性的消费者照片组成,并且包含姿势,照明和遮挡的大变化。 自从介绍以来,VOC 的挑战一直很受欢并且逐年更新并适应社区的需求直到 2012 年计划结束。而 2005 年的第一个挑战只有 4 个不同的类,2007 年引入了 20 个不同的对象类。多年来,基准规模在 2012 年达到总共 11,530 张图像当中共有 27,450 张 ROI 注释物体。 2014 年,Lin 等 (2014)介绍了 Microsoft COCO 数据集,用于物体检测,实例分割和上下文推理。 它们在自然环境中提供包含常见对象的复杂日常场景的图像。 数据集总共包括 91 个对象类,250 万个注释实例和 328k 个图像。 Microsoft COCO 在 PASCAL VOC 对象分割基准测试中每个类的实例数显著增加。 所有物体都在广泛的人群工作人员的努力下对每个实例进行标注。 与 PASCAL VOC 类似,IOU 度量用于评估。 Tracking: Leal-Taix´e et al. (2015); Milan et al. (2016) present the MOTChallenge16 which addresses the lack of a centralized benchmark for multi object tracking. The benchmark contains 14 challenging video sequences in unconstrained environments filmed with static and moving cameras and subsumes many existing multi-object tracking benchmarks such as PETS (Ferryman & Shahrokni (2009)) and KITTI (Geiger et al.(2012b)). The annotations for three object classes are provided: moving or standing pedestrians, people that are not in an upright position and others. They use the two popular tracking measures, Multiple Object Tracking Accuracy (MOTA) and Multiple Object Tracking Precision (MOTP) introduced by Stiefelhagen et al. (2007) for the evaluation of the approaches. Detection ground truth provided by the authors allows to analyze the performance of tracking systems independent of a detection system. Methods using a detector and methods using the detection ground truth can be compared separately on their website. - Aerial Image Datasets: The ISPRS benchmark17 (Rottensteiner et al. (2013, 2014)) provides data acquired by airborne sensors for urban object detection and 3D building reconstruction and segmentation. It consists of two datasets: Vaihingen and Downtown Toronto. The object classes considered in the object detection task are building, road, tree, ground, and car. The Vaihingen dataset provides three areas with various object classes and a large test site for road detection algorithms. The Downtown Toronto dataset covers an area of about 1.45 km2 in the central area of Toronto, Canada. Similarly to Vaihingen, there are two smaller areas for object extraction and building reconstruction, as well as one large area for road detection. For each test area, aerial images with orientation parameters, digital surface model (DSM), orthophoto mosaic and airborne laser scans are provided. The quality of the approaches is assessed using several metrics for detection and reconstruction. In both cases completeness, correctness and quality is assessed on a per-area level and a per-object level. 追踪:Leal-Taix’e(2015),Milan(2016)提出了 MOTChallenge16,解决了多对象跟踪缺乏集中的基准。该基准测试包含 14 个具有静态和移动摄像机拍摄的无约束环境的挑战性视频序列,并包含许多现有的多对象跟踪基准,如 PETS(Ferryman&Shahrokni(2009))和 KITTI(Geiger 等(2012b))。提供三个对象类的注释:移动或站立的行人,不在直立位置的人等。他们使用 Stiefelhagen 等人介绍的两个流行的跟踪措施,多目标跟踪精度(MOTA)和多对象跟踪精度(MOTP)。 (2007)评估方法。作者提供的检测基准真实性可以分析独立于检测系统的跟踪系统的性能。使用检测器的方法和使用检测基准的方法可以在其网站上单独进行比较。 - 空中图像数据集:ISPRS benchmark17(Rottensteiner 等(2013,2014))提供了用于城市物体检测和 3D 建筑重建和分割的机载传感器获取的数据。它包括两个数据集:Vaihingen 和多伦多市区。对象检测任务中考虑的对象类是建筑,道路,树木,地面和汽车。 Vaihingen 数据集提供了三个不同对象类别的区域和一个用于道路检测算法的大型测试站点。多伦多市中心数据集在加拿大多伦多的中部地区面积约 1.45 平方公里。与 Vaihingen 类似,有两个较小的对象提取和建筑重建区域,以及一个大面积的道路检测。对于每个测试区域,提供具有取向参数,数字表面模型(DSM),正射影像马赛克和机载激光扫描的航空图像。使用检测和重建的几个度量来评估方法的质量。在这两种情况下,完整性,正确性和质量都在每个面积水平和每个物体水平上进行评估。 Autonomous Driving: In 2012, Geiger et al. (2012b, 2013) have introduced the KITTI Vision Benchmark18 for stereo, optical flow, visual odometry/SLAM and 3D object detection (Figure). The dataset has been captured from an autonomous driving platform and comprises six hours of recordings using high-resolution color and grayscale stereo cameras, a Velodyne 3D laser scanner and high-precision GPS/IMU inertial navigation system. The stereo and optical flow benchmarks derived from this dataset comprise 194 training and 195 test image pairs at a resolution of 1280 376 pixels and sparse ground truth obtained by projecting accumulated 3D laser point clouds onto the image. Due to the limitations of the rotating laser scanner used as reference sensor, the stereo and optical flow benchmark is restricted to static scenes with camera motion. To provide ground truth motion fields for dynamic scenes, Menze & Geiger (2015) have annotated 400 dynamic scenes, fitting accurate 3D CAD models to all vehicles in motion in to order to obtain flow and stereo ground truth for these objects. The KITTI flow and stereo benchmarks use the percentage of erroneous (bad) pixels to assess the performance of the submitted methods. Additionally, Menze & Geiger (2015) combined the stereo and flow ground truth to form a novel 3D scene flow benchmark. For evaluating scene flow, they combine classical stereo and optical flow measures. The visual odometry / SLAM challenge consists of 22 stereo sequences, with a total length of 39.2 km. The ground truth pose is obtained using GPS/IMU localization unit which was fed with RTK correction signals. The translational and rotational error averaged over a particular trajectory length is considered for evaluation. For the KITTI object detection challenge, a special 3D labeling tool has been developed to annotate all 3D objects with 3D bounding boxes for 7481 training and 7518 test images. The benchmark for the object detection task was separated into a vehicle, pedestrian and cyclist detection tasks, allowing to focus the analysis on the most important problems in the context of autonomous vehicles. Following PASCAL VOC Everingham et al. (2010), the intersection-over-union (IOU) metric is used for evaluation. For an additional evaluation, this metric has been extended to capture both 2D detection and 3D orientation estimation performance. A true 3D evaluation is planned to be released shortly. The KITTI benchmark was extended by Fritsch et al. (2013) to the task of road/lane detection. In total, 600 diverse training and test images have been selected for manual annotation of road and lane areas. Mattyus et al. (2016) used aerial images to enhance the KITTI dataset with fine grained segmentation categories such as parking spots and sidewalk as well as the number and location of road lanes. The KITTI dataset has established itself as one of the standard benchmarks in all of the aforementioned tasks, in particular in the context of autonomous driving applications. 2012 年,Geiger 等(2012b,2013)推出了用于立体声,光流,视觉测距/ SLAM 和 3D 物体检测的 KITTI Vision Benchmark18(图)。数据集已从自主驾驶平台捕获,包括使用高分辨率彩色和灰度立体相机的六小时录音,Velodyne 3D 激光扫描仪和高精度 GPS / IMU 惯性导航系统。从该数据集派生的立体声和光流基准测试包括 194 次训练和 195 个测试图像对,分辨率为 1280?通过将累积的 3D 激光点云投影到图像上获得的 376 个像素和稀疏的地面真实。由于用作参考传感器的旋转激光扫描仪的局限性,立体声和光学流量基准仅限于具有摄像机运动的静态场景。 为了为动态场景提供地面真相运动场,Menze&Geiger(2015)已 经注明了 400 个动态场景,将精确的 3D CAD 模型适用于所有运动的车辆,以获得这些物体的流动和立体声地面实况。 KITTI 流量和立体声基准使用错误(不良)像素的百分比来评估提交的方法的性能。此外,Menze&Geiger(2015)结合了立体声和流动地面的真相,形成了一种新颖的 3D 场景流动基准。为了评估场景流,它们结合了古典立体声和光学流量测量。 视觉测距/ SLAM 挑战包括 22 个立体声序列,总长 39.2 公里。使用馈送有 RTK 校正信号的 GPS / IMU 定位单元获得地面真实姿势。考虑在特定轨迹长度上平均的平移和旋转误差进行评估。 对于 KITTI 对象检测挑战,已经开发了一种特殊的 3D 标签工具,用于通过 3D 边界框注释所有 3D 对象,用于 7481 个训练和 7518 个测试图像。物体检测任务的基准被分为车辆,行人和骑车人员检测任务,允许将分析集中在自主车辆的上下文中最重要的问题。按照 PASCAL VOC Everingham 等(2010),交叉联合(IOU)度量用于评估。为了进一步评估,该指标已扩展到捕获 2D 检测和 3D 定向估计性能。计划即将发布真正的 3D 评估。 由 Fritsch 等人扩展了 KITTI 基准。 (2013 年)到道路/车道检测任务。总共选择了 600 多种不同的训练和测试图像,用于手动注释道路和车道区域。 Mattyus 等人(2016)使用航空图像来增强 KITTI 数据集,并提供诸如停车位和人行道之类的细粒度细分类别,以及道路的数 量和位置。 KITTI 数据集已经成为所有上述任务的标准基准之一,特别是在自主驾驶应用的上下文中。 Complementary to other datasets, the HCI benchmark19 proposed in Kondermann et al. (2016) specifically includes realistic, systematically varied radiometric and geometric challenges. Overall, a total of 28,504 stereo pairs with stereo and flow ground truth is provided. In contrast to previous datasets, ground truth uncertainties have been estimated for all static regions. The uncertainty estimate is derived from pixel-wise error distributions for each frame which are computed based on Monte Carlo sampling. Dynamic regions are manually masked out and annotated with approximate ground truth for 3,500 image pairs. The major limitation of this dataset is that all sequences were recorded in a single street section, thus lacking diversity. On the other hand, this enabled better control over the content and environmental conditions. In contrast to the mobile laser scanning solution of KITTI, the static scene is scanned only once using a high-precision laser scanner in order to obtain a dense and highly accurate ground truth of all static parts. Besides the metrics used in KITTI and Middlebury, they use semantically meaningful performance metrics such as edge fattening and surface smoothness for evaluation Honauer et al. (2015). The HCI benchmark is rather new and not established yet but the controlled environment allows to simulate rarely occurring events such as accidents which are of great interest in the evaluation of autonomous driving systems. The Caltech Pedestrian Detection Benchmark20 proposed by Dollar et al. (2009) provides 250,000 frames of sequences recorded by a vehicle while driving through regular traffic in an urban environment. 350,000 bounding boxes and 2,300 unique pedestrians were annotated including temporal correspondence between bounding boxes and detailed occlusion labels. Methods are evaluated by plotting the miss rate against false positives and varying the threshold on detection confidence. The Cityscapes Dataset21 by Cordts et al. (2016) provides a benchmark and large-scale dataset for pixel-level and instancelevel semantic labeling that captures the complexity of realworld urban scenes. It consists of a large, diverse set of stereo video sequences recorded in streets of different cities. High quality pixel-level annotations are provided for 5,000 images while 20,000 additional images have been annotated with coarse labels obtained using a novel crowd sourcing platform. For two semantic granularities, i.e., classes and categories, they report mean performance scores and evaluate the intersection-overunion metric at instance-level to assess how well individual instances are represented in the labeling. The TorontoCity benchmark presented byWang et al. (2016) covers the greater Toronto area with 712 km2 of land, 8,439 km of road and around 400,000 buildings. The benchmark covers a large variety of tasks including building height estimation (reconstruction), road centerline and curb extraction, building instance segmentation, building contour extraction, semantic labeling and scene type classification. The dataset was captured from airplanes, drones, and cars driving around the city to provide different perspectives. 与其他数据集的补充,在 Kondermann 等人提出的 HCI 基准 19。 (2016)具体包括现实的,有系统地变化的辐射和几何挑战。总的来说,共提供了 28,504 立体声和流动地面真相的立体声对。与以前的数据集相比,所有静态区域的地面真实不确定度已被估计。不确定性估计是根据基于蒙特卡洛取样计算的每个帧的像素误差分布得出的。手动屏蔽动态区域并用 3,500 个图像对的近似地面实例进行注释。 这个数据集的主要限制是所有序列记录在单个街区,因此缺乏多样性。另一方面,这能够更好地控制内容和环境条件。与 KITTI 的移动激光扫描解决方案相比,静态场景仅使用高精度激光扫描仪扫描一次,以获得所有静态部件的致密和高精度的地面实况。除了 KITTI 和 Middlebury 使用的指标之外,他们使用语义有意义的性能指标,如边缘育肥和表面平滑度评估 Honauer 等。 (2015 年)。 HCI 基准相当新,尚未建立,但受控环境允许模拟很少发生的事件,例如对自主驾驶系统的评估感兴趣的事故。 美国加州大学提出的 Caltech 行人检测基准 20 (2009)提供了车辆记录的 25 万帧序列,同时在城市环境中经常进行交通。包括 350,000 个边界框和 2,300 个独特的行人,包括边界框和详细遮挡标签之间的时间对应关系。通过绘制误差率与误报率并在检测置信度上改变阈值来评估方法。 由 Cordts 等人的 Cityscapes Dataset21 (2016)为像素级和实例级语义标注提供了基准和大型数据集,捕捉到现实城市场景的复杂性。它由不同城市的街道上记录的大型,多样化的立体视频序列组成。为 5,000 张图像提供了高质量的像素级注释,而使用新颖的人群采购平台获得的粗略标签已经注明了 20,000 张附加图像。对于两个语义粒度,即类别和类别,他们报告平均绩效评分,并评估实例级别的交叉点平均度量,以评估在标签中表示个体实例的程度。 Wang 等人提出的多伦多城市基准(2016 年)覆盖多伦多地区,712 平方公里的土地,8,439 公里的道路和大约 40 万个建筑物。该基准涵盖了建筑高度估计(重建),道路中心线和路缘提取,建筑物实例分割,建筑轮廓提取,语义标注和场景类型分类等各种任务。数据集被从飞机,无人驾驶飞机和汽车驾驶在城市周围捕获,以提供不同的观点。 Long-Term Autonomy: Several datasets such as KITTI or Cityscapes focus on the development of algorithmic competences for autonomous driving but do not address challenges of long-term autonomy, as for examples environmental changes over time. To address this problem, a novel dataset for autonomous driving has been presented by Maddern et al. (2016). They collected images, LiDAR and GPS data while traversing 1,000 km in central Oxford in the UK during one year. This allowed them to capture large variations in scene appearance due to illumination, weather and seasonal changes, dynamic objects, and constructions. Such long-term datasets allow for in-depth investigation of problems that detain the realization of autonomous vehicles such as localization in different times of the year. 长期自动:几个数据集,如 KITTI 或 Cityscapes,着重于开发自主驾驶的算法能力,但不能解决长期自主的挑战,例如随着时间的推移环境变化。 为了解决这个问题,Maddern 等人提出了一个用于自主驾驶的新型数据集。(2016)。 他们在一年内在英国牛津中心穿过 1000 公里的地方收集图像,LiDAR 和 GPS 数据。 这允许他们捕获由于照明,天气和季节变化,动态对象和结构而导致的场景外观的大变化。 这些长期数据集允许深入调查在一年中的不同时期扣留自主车辆的实现问题,例如本地化。 Synthetic Data The generation of ground truth for real examples is very labor intensive and often not even possible at large scale when pixel-level annotations are required. On the other hand, pixel-level ground truth for large-scale synthetic datasets can be easily acquired. However, the creation of realistic virtual world is time-consuming. The popularity of movies and video games have led to an industry creating very realistic 3D content which nourishes the hope to replace real data completely using synthetic datasets. Consequently, several synthetic datasets have been proposed, recently, but it remains an open question whether the realism and variety attained is sufficient to replace real world datasets. Besides, creating realistic virtual content is a time consuming and expensive process itself and the trade-off between real and synthetic (or augmented) data is not clear yet. 为真实的例子生成地面真相是非常劳动密集型的,并且在需要像素级注释时通常甚至不可能大规模地实现。 另一方面,可以轻松获取大规模合成数据集的像素级地面实况。 然而,创造现实的虚拟世界是耗时的。 电影和视频游戏的普及导致了行业创造了非常逼真的 3D 内容,这些内容丰富了使用合成数据集完全替代实际数据的希望。 因此,最近已经提出了几个合成数据集,但是现实主义和品种是否足以替代现实世界数据集仍然是一个悬而未决的问题。 此外,创建逼真的虚拟内容是一个耗时且昂贵的过程本身,真实和合成(或增强)数据之间的权衡尚不清楚。 MPI Sintel: The MPI Sintel Flow benchmark22 presented by Butler et al. (2012) takes advantage of the open source movie Sintel, a short animated film, to render scenes of varying complexity with optical flow ground truth. In total, Sintel comprises 1,628 frames. Different datasets obtained using different passes of the rendering pipeline vary in complexity shown in Figure 3. The albedo pass has roughly piecewise constant colors without illumination effects while the clean pass introduces illumination of various kinds. The final pass adds atmospheric effects, blur, color correction and vignetting. In addition to the average endpoint error, the benchmark website provides different rankings of the methods based on speed, occlusion boundaries, and disocclusions. Flying Chairs and Flying Things: The limited size of optical flow datasets hampered the training of deep high-capacity models. To train a convolutional neural network, Dosovitskiy et al.(2015) thus introduced a simple synthetic 2D dataset of flying chairs rendered on top of random background images from Flickr. As the limited realism and size of this dataset proved insufficient to learn highly accurate models, Mayer et al. (2016) presented another large-scale dataset consisting of three synthetic stereo video datasets: FlyingThings3D, Monkaa, Driving. FlyingThings3D provides everyday 3D objects flying along randomized 3D trajectories in a randomly created scene. Inspired by the KITTI dataset a driving dataset has been created which uses car models from the same pool as FlyingThings3D and additionally highly detailed tree and building models from 3D Warehouse. Monkaa is an animated short movie similar to Sintel used in the MPI Sintel benchmark. Game Engines: Unfortunately, data from animated movies is very limited since the content is hard to change and such movies are rarely open source. In contrast, game engines allow for creating an infinite amount of data. One way to create virtual worlds using a game engine is presented by Gaidon et al. (2016) which introduces the Virtual KITTI dataset23. They present an efficient real-to-virtual world cloning method to create realistic proxy worlds. A cloned virtual world allows to vary conditions such as weather or illumination and to use different camera settings. This way, the proxy world can be used for virtual data augmentation to train deep networks. Virtual KITTI contains 35 photo-realistic synthetic videos with a total of 17,000 high resolution frames. They provide ground truth for object detection, tracking, scene and instance segmentation, depth and optical flow. MPI Sintel :由 Butler 等人提出的 MPI Sintel Flow benchmark22 (2012)利用开源电影 Sintel(短片动画),以光流地面的真相呈现不同复杂度的场景。总共有 Sintel 包括 1,628 帧。使用不同渲染流程获得的不同数据集的复杂度如图 3 所示。反照率传递具有大致分段恒定颜色,无照明效果,而清洁通道则引入各种照明。最后的通行证增加了大气效果,模糊,颜色校正和渐晕。除了平均终点误差之外,基准网站还提供了基于速度,遮挡边界和不相关的方法的不同排名。 飞行椅和飞行事物:光流数据集的数量有限,妨碍了深层大容量模型的训练。为了训练卷积神经网络,Dosovitskiy 等人(2015)引入了一个简单的合成 2D 数据集,它们呈现在 Flickr 的随机背景图像之上。由于该数据集的有限现实性和大小证明不足以学习高精度模型,Mayer 等(2016)提出了另外一个由三个合成立体视频数据集组成的大型数据集:FlyingThings3D,Monkaa,Driving。 FlyingThings3D 在随机创建的场景中提供随机 3D 轨迹飞行的每天 3D 对象。受 KITTI 数据集的启发,已经创建了一个驱动数据集,它使用与 FlyingThings3D 相同的池中的汽车模型,以及来自 3D Warehouse 的另外高度详细的树和建筑模型。 Monkaa 是一个类似于 Sintel 的动画短片,用于 MPI Sintel 基准测试。 游戏引擎:不幸的是,动画电影的数据非常有限,因为内容很难改变,这样的电影很少是开源的。相比之下,游戏引擎允许创建无限量的数据。 Gaidon 等人提出了使用游戏引擎创建虚拟世界的一种方式。 (2016)介绍了虚拟 KITTI 数据集 23。他们提出了一种高效的实时虚拟世界克隆方法来创建现实的代理世界。克隆的虚拟世界允许改变诸如天气或照明的条件,并使用不同的相机设置。这样,代理世界可以用于虚拟数据扩充来训练深层网络。虚拟 KITTI 包含 35 张照片合成视频,总共 17,000 个高分辨率帧。它们为物体检测,跟踪,场景和实例分割,深度和光流提供了基础。 In concurrent work, Ros et al. (2016) created SYNTHIA24, a synthetic collection of Imagery and Annotations of urban scenarios for semantic segmentation. They rendered a virtual city with the Unity Engine. The dataset consists of 13,400 randomly taken virtual images from the city and four video sequences with 200,000 frames in total. Pixel-level semantic annotations are provided for 13 classes. Richter et al. (2016) have extracted pixel-accurate semantic label maps for images from the commercial video game Grand Theft Auto V. Towards this goal, they developed a wrapper which operates between the game and the graphics hardware to obtain pixel-accurate object signatures across time and instances. The wrapper allows them to produce dense semantic annotations for 25 thousand images synthesized by the photorealistic open-world computer game with minimal human supervision. However, for legal reasons, the extracted 3D geometry can not be made publicly available. Similarly, Qiu & Yuille (2016) provide an open-source tool to create virtual worlds by accessing and modifying the internal data structure of Unreal Engine 4. They show how virtual worlds can be used to test deep learning algorithms by linking them with the deep learning framework Caffe Jia et al. (2014). 在并行工作中,Ros et al。 (2016)创建了 SYNTHIA24,一种用于语义分割的城市场景图像和注释的综合集合。他们用 Unity Engine 渲染了一个虚拟的城市。该数据集由 13,400 个随机抽取的城市虚拟图像和四个视频序列组成,共 20 万帧。为 13 个类提供像素级语义注释。 Richter et al。 (2016)已经为商业视频游戏“侠盗猎车手”V 提取了图像的像素精确语义标签贴图。为了实现这一目标,他们开发了一种在游戏和图形硬件之间运行的包装器,以便跨越时间获得像素精确的对象签名,实例。包装器允许他们通过最小的人力监督来生成由真实感的开放世界电脑游戏合成的 2.5 万张图像的密集语义注释。然而,出于法律原因,提取的 3D 几何不能公开获得。同样,Qiu&Yuille(2016)通过访问和修改虚幻引擎 4 的内部数据结构,提供了一个开源工具来创建虚拟世界。他们展示了虚拟世界如何通过将深度学习算法与深层次学习框架 Caffe Jia(2014)。]]></content>
<categories>
<category>paper</category>
</categories>
</entry>
<entry>
<title><![CDATA[各类排序算法实践]]></title>
<url>%2F2019%2F03%2F17%2Fsort%2F</url>
<content type="text"><![CDATA[比较重要的基础算法,简单罗列一下一些排序的实践过程 冒泡排序选择排序从待排序部分 a[i,m]选择最小元素,与待排序部分的第一个元素 a[i]交换,形成新的有序区间 a[1,i+1]选择排序总体实践复杂度 O(n^2) void selectSout(){ for(int i=1; i<=n; i++) { int flag = i; for(int j=i; j<=n; j++) { if(a[j] < a[flag]) flag = j; } // 交换a[i]和a[flag] int temp = a[i]; a[i] = a[flag]; a[flag] = temp; }} 插入排序 归并排序快速排序sort 函数运用]]></content>
<categories>
<category>code</category>
</categories>
<tags>
<tag>algorithm</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Autonomous Vehicles translate -- abstract & previous & history]]></title>
<url>%2F2019%2F03%2F14%2Fabstract-previous-history%2F</url>
<content type="text"><![CDATA[Computer Vision for Autonomous Vehicles:Problems, Datasets and State-of-the-Art自动驾驶技术的计算机视觉:问题,数据和前沿技术摘要,前沿和技术历史 Abstract 摘要 Recent years have witnessed amazing progress in AI related fields such as computer vision, machine learning and autonomous vehicles. |As with any rapidly growing field, however, it becomes increasingly difficult to stay up-to-date or enter the field as a beginner. |While several topic specific survey papers have been written, to date no general survey on problems, datasets and methods in computer vision for autonomous vehicles exists.|This paper attempts to narrow this gap by providing a state-of-the-art survey on this topic. Our survey includes both the historically most relevant literature as well as the current state-of-the-art on several specific topics, including recognition, reconstruction, motion estimation, tracking, scene understanding and end-to-end learning. |Towards this goal, we first provide a taxonomy to classify each approach and then analyze the performance of the state-of-the-art on several challenging benchmarking datasets including KITTI, ISPRS, MOT and Cityscapes. |Besides, we discuss open problems and current research challenges. To ease accessibility and accommodate missing references, we will also provide an interactive platform which allows to navigate topics and methods, and provides additional information and project links for each paper.Keywords: Computer Vision, Autonomous Vehicles, Autonomous Vision 概述:人类见证了最近几年 AI 相关领域的惊人进步,如计算机视觉,机器学习和自动驾驶。然而任何一个快速发展的领域,保持领先或刚开始进入这些领域变得越来越难(业内人员难以跟上行业节奏或者业外人员难入行)。尽管已经(有人)发表了一些这方面的专题研究文章,但在自动驾驶技术中,计算机视觉的问题、数据和方法至今没有普遍的研究。对于这个话题,这篇论文试图通过提供对前沿技术的研究来减少这种缺口。我们的研究包括最相关的历史资料和当前最前沿的技术,包括识别、重建运动估测、追踪场景理解和端到端学习等。为完成这个目标,我们首先通过分类学对每一个方法进行分类,然后在一些具有挑战性的基础数据集上,如 KITTI、ISPRS、MOT 和 Cityscapes 上分析每一个方法在前沿技术上的表现此外,我们还讨论了一些开放问题和当前研究的挑战,为了轻松访问和适应缺失的参考,我们将提供一个具有主题和方法的驾驶交互平台,并提供额外信息和每篇论文的项目链接关键词:计算机视觉,自动驾驶,自主视觉 previous 前言 Since the first successful demonstrations in the 1980s (Dick-manns & Mysliwetz (1992); Dickmanns & Graefe (1988); Thorpeet al. (1988)), great progress has been made in the field of autonomous vehicles. |Despite these advances, however, it is safe to believe that fully autonomous navigation in arbitrarily complex environments is still decades away. |The reason for this is two-fold: First, autonomous systems which operate in complex dynamic environments require artificial intelligence which generalizes to unpredictable situations and reasons in a timely manner. |Second, informed decisions require accurate perception, yet most of the existing computer vision systems produce errors at a rate which is not acceptable for autonomous navigation. 从 20 世纪 80 年代首次成功展示以来(Dick-manns & Mysliwetz (1992); Dickmanns & Graefe (1988); Thorpeet al. (1988))(Dick-manns & Mysliwetz (1992); Dickmanns & Graefe (1988); Thorpeet al. (1988)),自动驾驶技术领域已经取得了很大进展尽管有了这些进展,但在任意复杂环境中,实现完全自动驾驶仍然被认为需要几十年原因有两点:第一,在复杂的、动态的环境中运行的自动驾驶系统需要人工智能来归纳不可预测的情形和原因,给出及时的方法第二,信息的决策需要准确的感知,目前大多数已有的计算机视觉系统有一定的错误率,这是自动驾驶技术无法接受的 In this paper, we focus on the second aspect which we call autonomous vision and investigate the performance of current perception systems for autonomous vehicles. |Towards this goal, we first provide a taxonomy of problems and classify existing datasets and techniques using this taxonomy, describing the pros and cons of each method. Second, we analyze the current state-of-the-art performance on several popular publicly available benchmarking datasets. |In particular, we provide a novel in-depth qualitative analysis of the KITTI benchmark which shows the easiest and most difficult examples based on the methods submitted to the evaluation server. |Based on this analysis, we discuss open research problems and challenges. To ease navigation, we also provide an interactive online tool which visualizes our taxonomy using a graph and provides additional information and links to project pages in an easily accessible manner. |We hope that our survey will become a useful tool for researchers in the field of autonomous vision and lowers the entry barrier for beginners by providing an exhaustive overview over the field. 在这篇论文中,我们关注第二个方面的问题,也就是自动驾驶视觉,同时调查最近的自动驾驶视觉中感知系统的表现为完成这个目标,我们首先给出了问题的分类,归类了已有的数据和可使用的技术,描述每种方法的优缺点。第二,我们在几个流行的公开数据集上分析了最近前沿成果的表现特别是我们给出一种 KITTI 基准的新的深入定性分析,这些分析展示了提交给评价服务器的方法中最简单和最困难的例子基于这些分析,我们讨论了开放的研究问题和挑战,为了简化学习,我们也给出一个在线交互式工具,用图像可视化了分类,并提供额外信息和一个简单可行的方法与项目页链接我们希望我们的研究能够成为自动驾驶领域研究人员的一个有用的工具,并通过透彻的概述,降低新人进入该领域的门槛 There exist several other related surveys. Winner et al. (2015) explains in detail systems for active safety and driver assistance, considering both their structure and their function. |Their focus is to cover all aspects of driver assistance systems and the chapter about machine vision covers only the most basic concepts of the autonomous vision problem. |Klette (2015) provide an overview over vision-based driver assistance systems. They describe most aspects of the perception problem at a high level, but do not provide an in-depth review of the state-of-the-art in each task as we pursue in this paper. |Complementary to our survey, Zhu et al. (2017) provide an overview of environment perception for intelligent vehicles, focusing on lane detection, traffic sign/light recognition as well as vehicle tracking. |In contrast, our goal is to bridge the gap between the robotics, intelligent vehicles, photogrammetry and computer vision communities by providing an extensive overview and comparison which includes works from all fields. 目前也有一些其它相关的研究,Winner et al. (2015)详细地解释了主动安全性和驾驶辅助系统,同时考虑了它们的结构和功能这些研究注重覆盖辅助驾驶系统的所有方面,但关于机器视觉的章节只覆盖到了自动驾驶技术中最基础的概念。Klette (2015)提供了一个基于视觉的辅助驾驶系统的概述,他们描述了高层次感知问题的大部分方面,但并没有像我们在论文中追求的一样,给出在各种前沿任务中比较深入的评测Zhu et al. (2017)提出了智能汽车环境感知的概述,聚焦在车道检测,交通信号灯识别和机车追踪问题,这与我们的研究相互补充。相比较下,我们的目标是通过提供广泛的概述和比较,包括在这个领域所有的成果,在机器人、智能汽车、摄影测绘和计算机视觉之间建立起一座桥梁 History of Autonomous Driving 自动驾驶技术历史Autonomous Driving Projects 自动驾驶项目 Many governmental institutions worldwide started various projects to explore intelligent transportation systems (ITS). The PROMETHEUS project started 1986 in Europe and involved more than 13 vehicle manufacturers, several research units from governments and universities of 19 European countries. |One of the first projects in the United States was Navlab Thorpe et al. (1988) by the Carnegie Mellon University which achieved a major milestone in 1995, by completing the first autonomous drive from Pittsburgh, PA and Sand Diego, CA. |After many initiatives were launched by universities, research centers and automobile companies, the U.S. government established the National Automated Highway System Consortium (NAHSC) in 1995. |Similar to the U.S., Japan established the Advanced Cruise-Assist Highway System Research Association in 1996 among many automobile industries and research centers to foster research on automatic vehicle guidance. |Bertozzi et al. (2000) survey many approaches to the challenging task of autonomous road following developed during these projects. They concluded that suffcient computing power is become increasingly available, but diffculties like reflections, wet road, direct sunshine, tunnels and shadows still make data interpretation challenging. |Thus, they suggested the enhancement of sensor capabilities. They also pointed out that the legal aspects related to the responsibility and impact of automatic driving on human passengers need to be considered carefully. |In summary, the automation will likely be restricted to special infrastructures and will be extended gradually. 世界各地的许多政府机构启动各式各样的项目来开发智能交通系统(ITS)。PROMETHEUS 这个项目 1986 年在欧洲启动,包括超过 13 个交通工具生产商,当中的许多研究成员来自 19 个欧洲国家的政府和高校。美国的其中一个项目就是由卡耐基梅隆大学的 Navlab Thorpe 等人(1988)创建的。这个项目完成了第一次从 Pittsburgh,PA,Sand Diego 和 CA 的自动驾驶,在 1995 年是一个重要的里程碑。在许多大学,研究中心和自动驾驶公司的倡议下,美国政府在 1995 年成立了自动化公路系统联盟(NAHSC)。和美国一样,日本于 1996 年成立了高级巡航公路系统研究协会(Advanced Cruise-Assist Highway System Research Association),包括各大自动驾驶公司和研究中心,来促进自动驾驶导航的研究。Bertozzi 等人(2000)调查了许多具有挑战性的任务(通过这些项目发展的自动道路跟随),给出解决方法。他们得出结论,计算能力逐渐得到满足,但像反射,湿面潮湿,阳光直射,隧道和阴影这样的困难仍然使数据解释具有挑战性。因此,他们建议提高传感器性能,同时也指出,关系到自动驾驶对行人法律方面的责任和影响,应该认真的考虑总之,自动化技术(发展)可能会受限于特殊的基础设施,然后再慢慢的普及开来。 Motivated by the success of the PROMETHEUS projects to drive autonomously on highways, Franke et al. (1998) describe a real-time vision system for autonomous driving in complex urban traffic situations. |While highway scenarios have been studied intensively, urban scenes have not been addressed before. Their system included depth-based obstacle detection and tracking from stereo as well as a framework for monocular detection and recognition of relevant objects such as traffic signs. The fusion of several perception systems developed by Vis-Lab have led to several proto-type vehicles including ARGO Broggi et al. (1999), TerraMax Braid et al. (2006), and BRAiVE Grisleri & Fedriga (2010). |BRAiVE is the latest vehicle proto-type which is now integrating all systems that VisLab has developed so far. Bertozzi et al. (2011) demonstrated the robustness of their system at the VisLab Intercontinental Autonomous Challenge, a semi-autonomous drive from Italy to China. |The onboard system allows to detect obstacles, lane marking, ditches,berms and identify the presence and position of a preceding vehicle. The information produced by the sensing suite is used to perform different tasks such as leader-following and stop & go. PROMETHEUS 项目可以实现在高速公路上自动驾驶,在这个成功的案例推动下,Franke 等人描述了在复杂的城市交通场景下的自动驾驶的实时视觉系统。虽然在此之前公路场景情况已经有很多深入的研究,但城市场景却从未得到解决。他们的系统包括基于深度的障碍检测和立体追踪,以及针对相关物体(比如:交通信号)的单目检测和识别框架。 Vis-Lab 发展的多种传感系统的融合促成了几款原型车包括 ARGO Broggi(1999),TerraMax Braid(2006)和 BRAiVE Grisleri & Fedriga(2010)的出现BRAiVE 是目前 VisLab 开发的整合所有系统的最新车型。 Bertozzi 等人(2011)在 VisLab 洲际自治挑战赛(VisLab Intercontinental Autonomous Challenge,意大利到中国的半自主驾驶)展示了其系统的稳健性(鲁棒性)。车载系统允许检测障碍物,标记车道、沟渠、护堤,并识别前方是否存在车辆和车辆位置。感应套件提供的信息被用于执行不同的任务,如(leader-following)和前进/停止。? The PROUD project Broggi et al. (2015) slightly modified the BRAiVE prototype Grisleri & Fedriga (2010) to drive in urban roads and freeways open to regular traffic in Parma. |Towards this goal they enrich an openly licensed map with information about the maneuver to be managed (e.g. pedestrian crossing, traffic light, . . . ). |The vehicle was able to handle complex situations such as roundabouts, intersections, priority roads, stops, tunnels, crosswalks, traffic lights, highways, and urban roads without any human intervention. The V-Charge project Furgale et al. (2013) presents an electric automated car outfitted with close-to-market sensors. A fully operational system is proposed including vision-only localization, mapping, navigation and control. |The project supported many works on different problems such as calibration Heng et al. (2013, 2015), stereo H¨ane et al. (2014), reconstruction Haene et al. (2012, 2013, 2014), SLAM Grimmett et al.(2015) and free space detection H¨ane et al. (2015). In addition to these research objectives, the project keeps a strong focus on deploying and evaluating the system in realistic environments. PROUD 的项目 Broggi(2015)略微修改了 BRAiVE 原型 Grisleri & Fedriga(2010)使得汽车可以在 parma 城市道路和高速公路的常规交通情况下开车。为了实现这一目标,他们丰富了一份公开授权的地图,其中包含有待完成的机动信息(比如行人过路,交通信号灯等)。该车辆能够在没有人为干涉的情况下处理复杂的场景,例如回旋处,交叉口,优先道路,站点,隧道,人行横道,交通信号灯,高速公路和城市道路。 V-Charge 项目 Furgale 等人 (2013 年)提供配备了近距离市场(close-to-market)传感器的电动自动车。提出了一个全面可使用的系统,包括视觉定位,映射,导航和控制。该项目解决了诸多困难比如,Heng et al. (2013, 2015)的校准问题, H¨ane(2014)的立体问题,Haene(2012, 2013, 2014)的重建问题, Grimmett(2015)的 SLAM 问题和 H¨ane(2015)的空白区域检测的问题。除了这些研究目标,该项目还非常重视在现实环境中部署和系统评估。 Google started their self-driving car project in 2009 and completed over 1,498,000 miles autonomously until March 2016 in Mountain View, CA, Austin, TX and Kirkland, WA. |Different sensors (i.a. cameras, radars, LiDAR, wheel encoder, GPS) allow to detect pedestrians, cyclists, vehicles, road work and more in all directions. |According to their accident reports, Google’s self-driving cars were involved only in 14 collisions while 13 times were caused by others. In 2016, the project was split off to Waymo, an independent self-driving technology company. Tesla Autopilot is an advanced driver assistant system developed by Tesla which was first rolled out(推出) in 2015 with version of their software. The automation level of the system allows full automation but requires the full attention of the driver to take control if necessary. |From October 2016, all vehicles produced by Tesla were equipped with eight cameras, twelve ultrasonic sensors and a forward-facing radar to enable full self-driving capability. Google 于 2009 年开始了自驾车项目,直到 2016 年 3 月完成了超过 1,498,000 英里的驾驶距离,在美国加利福尼亚州奥斯汀市的 Mountain View,WA 和柯克兰。不同的传感器(例如摄像机,雷达,LiDAR,车轮编码器,GPS)可以全方位的检测行人,骑自行车的人,车辆,道路工作等等。据他们的事故报道,Google 的自动驾驶车只涉及 14 次碰撞,13 次是由别人造成的。 在 2016 年,这个项目分引入到了一家独立的自动驾驶技术公司 Waymo。 Tesla Autopilot 是由特斯拉开发的高级驾驶员辅助系统,该系统于 2015 年第一次推出其视觉软件。系统的自动化级别允许完全的自动化,但是仍然需要 要求驾驶员集中注意来控制。从 2016 年 10 月起,特斯拉生产的所有车辆配备了 8 台摄像机,12 台超声波传感器和一个前置雷达,以实现全自动驾驶能力。 Long Distance Test Demonstrations: In 1995 the team within the PROMETHEUS project Dickmanns et al. (1990); Franke et al. (1994); Dickmanns et al. (1994) performed the first autonomous long-distance drive from Munich, Germany, to Odense, Denmark, at velocities up to 175 km/h with about 95% autonomous driving. |Similarly, in the U.S. Pomerleau & Jochem (1996) drove from Washington DC to San Diego in the ’No hands across America’ tour with 98% automated steering yet manual longitudinal control. In 2014, Ziegler et al. (2014) demonstrated a 103 km ride from Mannheim to Pforzheim Germany, known as Bertha Benz memorial route, in nearly fully autonomous manner. |They present an autonomous vehicle equipped with close-to-production sensor hardware. Object detection and free-space analysis is performed with radar and stereo vision. Monocular vision is used for traffic light detection and object classification. |Two complementary vision algorithms, point feature based and lane marking based, allow precise localization relative to manually annotated digital road maps. They concluded that even thought the drive was successfully completed the overall behavior is far inferior to the performance level of an attentive human driver. 长距离测试演示:1995 年,PROMETHEUS 项目里 Dickmanns(1990)、Franke(1994)、Dickmanns(1994 年)的团队演示了从德国慕尼黑(Munich)到丹麦欧登塞(Odense)进行的第一次自动长途驾驶,速度达 175 公里/小时,其中约 95%为自主驾驶。同样,在美国 Pomerleau 和 Jochem(1996)在‘No hands across from America ???’中从华盛顿特区开往圣地亚哥,整个行程中有 98%的自动驾驶和偶尔的手动纵向控制。 2014 年,Zieglar(2014)以近乎完全自动的方式,展示了从曼海姆(Mannheim)到德国普福尔茨海姆(Pforzheim Germany)的 103km 的骑行,也就是众人所熟知的 Bertha Benz 纪念路线。他们展示了一种装配有接近生产(close-to-production)的传感器硬件的自动驾驶车辆。由雷达 radar 和立体视觉来进行物体检测和空白区域分析。单目视觉用来检测交通信号灯和目标分类。两种互补的算法,基于点特征和基于场景标记,允许相对于手动注释的数字路线图进行精确定位。他们得出结论,甚至认为自动驾驶虽然成功完成了,但是整体行为远远达不到细心的驾驶司机的水平。 Recently, Bojarski et al. (2016) drove autonomously 98% of the time from Holmdel to Atlantic Highlands in Monmouth County NJ as well as 10 miles on the Garden State Parkway without intervention. |Towards this goal, a convolutional neural network which predicts vehicle control directly from images is used in the NVIDIA DRIVETM PX self-driving car. The system is discussed in greater detail in Section 11. While all aforementioned performed impressively, the general assumption of precisely annotated road maps as well as prerecorded maps for localization demonstrates that autonomous systems are still far from human capabilities. |Most importantly, robust perception from visual information but also general artificial intelligence are required to reach human level reliability and react safely even in complex innercity situations. 最近,Bojarski(2016)从霍尔姆德尔(Holmdel)到新泽西州蒙茅斯县(Monmouth)的大西洋高原,以及在花园州立大道没有任何干扰的自动行驶了 10 英里,其中 98%是在自动驾驶。为了实现这一目标,在 NVIDIA DRIVETM PX 自动驾驶车中使用了一种从图像直接预测车辆控制的卷积神经网络。该系统在第 11 节中有更详细的讨论。 虽然所有上述表现令人印象深刻,但精确注释路线图的一般假设,以及用于定位的预先载入的地图证实了自主性系统仍然差强人意。最重要的是,这不仅需要视觉信息的强大的感知,也需要一般的人工智能达到和人一样的可靠性,并且在复杂的城市情况下也能安全地做出反应。 Autonomous Driving Competitions 自动驾驶竞赛 The European Land Robot Trial (ELROB) is a demonstration and competition of unmanned systems in realistic scenarios and terrains, focusing mainly on military aspects such as reconnaissance and surveillance, autonomous navigation and convoy transport. In contrast to autonomous driving challenges, ELROB scenarios typically include navigation in rough terrain. The first autonomous driving competition focusing on road scenes (though primarily dirt roads) has been initiated by the American Defense Advanced Research Projects Agency (DARPA) in 2004. The DARPA Grand Challenge 2004 offered a prize money of 1 million for the team first finishing a 150 mile route which crossed the border from California to Nevada. |However, none of the robot vehicles completed the route. One year later, in 2005, DARPA announced a second edition of its challenge with 5 vehicles successfully completing the route (Buehler et al.(2007)). The third competition of the DARPA Grand Challenge, known as the Urban Challenge (Buehler et al. (2009)), took place on November 3, 2007 at the site of the George Air Force Base in California. The challenge involved a 96 km urban area course where traffic regulations had to be obeyed while negotiating with other vehicles and merging into traffic. The Grand Cooperative Driving Challenge (GCDC, see also Geiger et al. (2012a)), a competition focusing on autonomous cooperative driving behavior was held in Helmond, Netherlands in 2011 for the first time and in 2016 for a second edition. During the competition, teams had to negotiate convoys, join convoys and lead convoys. The winner was selected based on a system that assigned points to randomly mixed teams. European Land Robot Trial (ELROB)是现实场景和地形中无人系统的示范与竞赛,主要集中在军事方面,如侦察监视,自动导航和车队运输。与自主驾驶挑战相反,ELROB 场景通常包括崎岖地形的导航。 2004 年,美国国防高级研究计划署(DARPA)发起了第一个专注于道路场景(主要是泥土路)的自动驾驶比赛。挑战赛提供了 100 万美元的奖金给首先完成从加利福尼亚州内华达州过境的 150 英里的路线。然而,机器人车辆都没有完成路线。 一年后,DARPA 公布了第二版的挑战,5 辆车顺利完成了路线(Buehler(2007))。DARPA 大挑战赛的第三场比赛,被称为城市挑战赛(Buehler(2009)),于 2007 年 11 月 3 日在乔治航空加利福尼亚州的基地。这个挑战涉及到一个 96 公里的城市地区航线,在这段路程中车辆在对其他车辆进行判断并汇合车流时,必须遵守交通法规。 专注于自动合作驾驶行为的大型合作驾驶挑战(GCDC,Geiger et al(2012a))在荷兰赫尔蒙德(Helmond)举行,2011 年首次,2016 年第二次。在比赛中,团队需要判断,加入和引导车队。获胜者是基于给随机混合团队分配点数的系统选出来的。]]></content>
<categories>
<category>paper</category>
</categories>
</entry>
<entry>
<title><![CDATA[PHP & MySQL learning notes (4)]]></title>
<url>%2F2019%2F03%2F03%2Fphp-notes3%2F</url>
<content type="text"><![CDATA[由于 PHP 和 MySQL 版本问题,对 PHP & MySQL learning notes (1) 中曾经写过用的 PHP 操作 MySQL 数据库进行笔记更新完善 PHP & MySQL learning notes (3) 中的代码重新用 MySQLi (面向对象) MySQLi (面向过程) PDO 三种方式演示 PHP 操作 MySQL 可以通过 phpinfo() 查看 mysqli 和 PDO 是否可以使用 连接 MySQL创建连接面向对象 <?php$servername = "localhost";$username = "username";$password = "password";// 创建连接$conn = new mysqli($servername, $username, $password);// 检测连接if ($conn->connect_error) { die("连接失败: " . $conn->connect_error);}echo "连接成功";?> 面向过程 <?php$servername = "localhost";$username = "username";$password = "password";// 创建连接$conn = mysqli_connect($servername, $username, $password);// 检测连接if (!$conn) { die("Connection failed: " . mysqli_connect_error());}echo "连接成功";?> PDO <?php$servername = "localhost";$username = "username";$password = "password";try { $conn = new PDO("mysql:host=$servername;", $username, $password); echo "连接成功";}catch(PDOException $e){ echo $e->getMessage();}?> 关闭链接$conn->close(); //面向对象mysqli_close($conn); //面向过程$conn = null; //实例PDO 创建数据库面向对象 <?php$servername = "localhost";$username = "username";$password = "password";// 创建连接$conn = new mysqli($servername, $username, $password);// 检测连接if ($conn->connect_error) { die("连接失败: " . $conn->connect_error);}// 创建数据库$sql = "CREATE DATABASE myDatabase";if ($conn->query($sql) === TRUE) { echo "数据库创建成功";} else { echo "Error creating database: " . $conn->error;}$conn->close();?> 面向过程 <?php$servername = "localhost";$username = "username";$password = "password";// 创建连接$conn = mysqli_connect($servername, $username, $password);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());}// 创建数据库$sql = "CREATE DATABASE myDatabase";if (mysqli_query($conn, $sql)) { echo "数据库创建成功";} else { echo "Error creating database: " . mysqli_error($conn);}mysqli_close($conn);?> PDO <?php$servername = "localhost";$username = "username";$password = "password";try { $conn = new PDO("mysql:host=$servername", $username, $password); // 设置 PDO 错误模式为异常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "CREATE DATABASE myDatabasePDO"; // 使用 exec() ,因为没有结果返回 $conn->exec($sql); echo "数据库创建成功<br>";}catch(PDOException $e){ echo $sql . "<br>" . $e->getMessage();}$conn = null;?> 创建数据表 CREATE创建 Mytest 表 CREATE TABLE Mytest ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL, email VARCHAR(50), reg_date TIMESTAMP) 面向对象 <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabase";// 创建连接$conn = new mysqli($servername, $username, $password, $dbname);// 检测连接if ($conn->connect_error) { die("连接失败: " . $conn->connect_error);}// 使用 sql 创建数据表$sql = "CREATE TABLE Mytest (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,firstname VARCHAR(30) NOT NULL,lastname VARCHAR(30) NOT NULL,email VARCHAR(50),reg_date TIMESTAMP)";if ($conn->query($sql) === TRUE) { echo "Table Mytest created successfully";} else { echo "创建数据表错误: " . $conn->error;}$conn->close();?> 面向过程 <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabase";// 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("连接失败: " . mysqli_connect_error());}// 使用 sql 创建数据表$sql = "CREATE TABLE Mytest (id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,firstname VARCHAR(30) NOT NULL,lastname VARCHAR(30) NOT NULL,email VARCHAR(50),reg_date TIMESTAMP)";if (mysqli_query($conn, $sql)) { echo "数据表 Mytest 创建成功";} else { echo "创建数据表错误: " . mysqli_error($conn);}mysqli_close($conn);?> PDO <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabasePDO";try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // 设置 PDO 错误模式,用于抛出异常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 使用 sql 创建数据表 $sql = "CREATE TABLE MyTest ( id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY, firstname VARCHAR(30) NOT NULL, lastname VARCHAR(30) NOT NULL, email VARCHAR(50), reg_date TIMESTAMP )"; // 使用 exec() ,没有结果返回 $conn->exec($sql); echo "数据表 MyTest 创建成功";}catch(PDOException $e){ echo $sql . "<br>" . $e->getMessage();}$conn = null;?> 插入数据 INSERT使用 INSERT 进行插入操作 INSERT INTO table_name (column1, column2, column3,...)VALUES (value1, value2, value3,...) 插入单条数据面向对象 <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabase";// 创建连接$conn = new mysqli($servername, $username, $password, $dbname);// 检测连接if ($conn->connect_error) { die("连接失败: " . $conn->connect_error);}$sql = "INSERT INTO MyTest (firstname, lastname, email)VALUES ('John', 'Doe', '[email protected]')";if ($conn->query($sql) === TRUE) { echo "新记录插入成功";} else { echo "Error: " . $sql . "<br>" . $conn->error;}$conn->close();?> 面向过程 <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabase";// 创建连接$conn = mysqli_connect($servername, $username, $password, $dbname);// 检测连接if (!$conn) { die("Connection failed: " . mysqli_connect_error());}$sql = "INSERT INTO MyTest (firstname, lastname, email)VALUES ('John', 'Doe', '[email protected]')";if (mysqli_query($conn, $sql)) { echo "新记录插入成功";} else { echo "Error: " . $sql . "<br>" . mysqli_error($conn);}mysqli_close($conn);?> PDO <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabasePDO";try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // 设置 PDO 错误模式,用于抛出异常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $sql = "INSERT INTO MyTest (firstname, lastname, email) VALUES ('John', 'Doe', '[email protected]')"; // 使用 exec() ,没有结果返回 $conn->exec($sql); /* $conn->exec("INSERT INTO MyTest (firstname, lastname, email) VALUES ('John', 'Doe', '[email protected]')") */ echo "新记录插入成功";}catch(PDOException $e){ echo $sql . "<br>" . $e->getMessage();}$conn = null;?> 插入多条数据mysqli_multi_query() 函数可用来执行多条 SQL 语句 $sql = "INSERT INTO MyTest (firstname, lastname, email)VALUES ('John', 'Doe', '[email protected]');";$sql .= "INSERT INTO MyTest (firstname, lastname, email)VALUES ('Mary', 'Moe', '[email protected]');";$sql .= "INSERT INTO MyTest (firstname, lastname, email)VALUES ('Julie', 'Dooley', '[email protected]')";$conn->multi_query($sql) === TRUE // 面向对象mysqli_multi_query($conn, $sql) //面向过程 PDO 需要使用事务函数执行多条并提交,执行失败后要使用回滚 <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabasePDO";try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // set the PDO error mode to exception $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 开始事务 $conn->beginTransaction(); // SQL 语句 $conn->exec("INSERT INTO MyTest (firstname, lastname, email) VALUES ('John', 'Doe', '[email protected]')"); $conn->exec("INSERT INTO MyTest (firstname, lastname, email) VALUES ('Mary', 'Moe', '[email protected]')"); $conn->exec("INSERT INTO MyTest (firstname, lastname, email) VALUES ('Julie', 'Dooley', '[email protected]')"); // 提交事务 $conn->commit(); echo "新记录插入成功";}catch(PDOException $e){ // 如果执行失败回滚 $conn->rollback(); echo $sql . "<br>" . $e->getMessage();}$conn = null;?> 使用预处理语句优化用于执行多个相同的 SQL 语句,也可以防止 MySQL 注入 主要优势 预处理语句大大减少了分析时间,只做了一次查询(虽然语句多次执行) 绑定参数减少了服务器带宽,你只需要发送查询的参数,而不是整个语句 预处理语句针对 SQL 注入是非常有用的,因为参数值发送后使用不同的协议,保证了数据的合法性 流程 预处理:创建 SQL 语句模板并发送到数据库。预留的值使用参数 ? 标记,可以将其替换为整型,字符串,双精度浮点型和布尔值INSERT INTO MyTest (firstname, lastname, email) VALUES(?, ?, ?) 绑定 SQL 参数并告知相关的值$stmt->bind_param("sss", $firstname, $lastname, $email); “sss” 参数列处理参数的数据类型,参数有以下四种类型:i - integer(整型)d - double(双精度浮点型)s - string(字符串)b - BLOB(binary large object:二进制大对象) 通过告诉数据库参数的数据类型,可以降低 SQL 注入的风险 数据库解析,编译,对 SQL 语句模板执行查询优化,并存储结果不输出 执行:最后,将应用绑定的值传递给参数(? 标记),数据库执行语句 使用预处理语句插入多条数据 // 检测数据库链接状态 同上// 预处理及绑定$stmt = $conn->prepare("INSERT INTO MyTest (firstname, lastname, email) VALUES (?, ?, ?)");$stmt->bind_param("sss", $firstname, $lastname, $email);// 设置参数并执行$firstname = "John";$lastname = "Doe";$email = "[email protected]";$stmt->execute();$firstname = "Mary";$lastname = "Moe";$email = "[email protected]";$stmt->execute();$firstname = "Julie";$lastname = "Dooley";$email = "[email protected]";$stmt->execute();echo "新记录插入成功";$stmt->close();$conn->close(); PDO <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabasePDO";try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); // 设置 PDO 错误模式为异常 $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // 预处理 SQL 并绑定参数 $stmt = $conn->prepare("INSERT INTO MyTest (firstname, lastname, email) VALUES (:firstname, :lastname, :email)"); $stmt->bindParam(':firstname', $firstname); $stmt->bindParam(':lastname', $lastname); $stmt->bindParam(':email', $email); // 插入行 $firstname = "John"; $lastname = "Doe"; $email = "[email protected]"; $stmt->execute(); // 插入其他行 $firstname = "Mary"; $lastname = "Moe"; $email = "[email protected]"; $stmt->execute(); // 插入其他行 $firstname = "Julie"; $lastname = "Dooley"; $email = "[email protected]"; $stmt->execute(); echo "新记录插入成功";}catch(PDOException $e){ echo "Error: " . $e->getMessage();}$conn = null;?> 查询数据 SELECT简单查询SELECT 语句用于从数据表中读取数据:SELECT column_name(s) FROM table_name 面向对象 设置 SQL 语句从 MyTest 数据表中读取 id, firstname 和 lastname 三个字段。 使用 SQL 语句从数据库中取出结果集并赋给复制给变量 $result。 函数 num_rows() 判断返回的数据。 函数 fetch_assoc() 将结合集放入到关联数组并循环输出 <?php// 创建和检测连接// 建立索引$sql = "SELECT id, firstname, lastname FROM MyTest";$result = $conn->query($sql);if ($result->num_rows > 0) { // 输出数据 while($row = $result->fetch_assoc()) { echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>"; }} else { echo "0 结果";}$conn->close();?> 面向过程 <?php// 创建并检测连接$sql = "SELECT id, firstname, lastname FROM MyTest";$result = mysqli_query($conn, $sql);if (mysqli_num_rows($result) > 0) { // 输出数据 while($row = mysqli_fetch_assoc($result)) { echo "id: " . $row["id"]. " - Name: " . $row["firstname"]. " " . $row["lastname"]. "<br>"; }} else { echo "0 结果";}mysqli_close($conn);?> PDO <?php$servername = "localhost";$username = "username";$password = "password";$dbname = "myDatabasePDO";try { $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password); $conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $stmt = $conn->prepare("SELECT id, firstname, lastname FROM MyTest "); $stmt->execute(); // 设置结果集为关联数组 $result = $stmt->setFetchMode(PDO::FETCH_ASSOC); foreach(new TableRows(new RecursiveArrayIterator($stmt->fetchAll())) as $k=>$v) { echo $v; }}catch(PDOException $e) { echo "Error: " . $e->getMessage();}$conn = null;echo "</table>";?> 使用 WHERE 子句, ORDER BY 子句进行查询时,必须使用 mysqli::query 或 mysqli_query() ,用于向 MySQL 连接发送查询或命令 修改数据 UPDATEUPDATE table_nameSET column1=value, column2=value2,...WHERE some_column=some_value 必须使用 mysqli::query 或 mysqli_query() <?php$con=mysqli_connect("localhost","username","password","database");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}mysqli_query($con,"UPDATE Persons SET Age=36WHERE FirstName='Peter' AND LastName='Griffin'");mysqli_close($con);?> 删除数据 DELETEDELETE FROM table_nameWHERE some_column = some_value <?php$con=mysqli_connect("localhost","username","password","database");// 检测连接if (mysqli_connect_errno()){ echo "连接失败: " . mysqli_connect_error();}mysqli_query($con,"DELETE FROM Persons WHERE LastName='Griffin'");mysqli_close($con);?> 使用的类和函数汇总mysqli PHP 和 Mysql 数据库之间的一个连接mysqli::init — 初始化 MySQLi 并返回一个资源类型的值,这个值可以作为 mysqlireal_connect() 函数的传入参数mysqli::$info — 返回最近执行的 SQL 语句的信息mysqli::stat — 获取当前系统状态信息mysqli::$connect_error/mysqli_connect_error() — 返回最后连接错误描述mysqli::$error/mysqli_error() — 返回最后的错误描述mysqli::\_construct/mysqli_connect() — 开始一个新的 MySQL 服务连接mysqli::real_connect — 建立一个 MySQL 服务器连接mysqli::select_db — 选择用于数据库查询的默认数据库mysqli::query — 对数据库执行一次查询mysqli::real_query — 执行一个 mysql 查询mysqli::send_query — 发送请求并返回结果mysqli::multi_query — 执行查询mysqli::real_escape_string — 根据当前连接的字符集,对于 SQL 语句中的特殊字符进行转义mysqli::prepare — 准备执行一个 SQL 语句mysqli::stmt_init — 初始化一条语句并返回一个用于 mysqli_stmt_prepare(调用)的对象mysqli::rollback — 回退当前事务mysqli::close/mysqli_close() — 关闭先前打开的数据库连接 mysqli::autocommit — 打开或关闭本次数据库连接的自动命令提交事务模式mysqli::change_user — 改变指定数据库连接的用户mysqli::character_set_name — 返回当前数据库连接的默认字符编码mysqli::commit — 提交一个事务mysqli::$connect_errno — 返回最后连接错误代码mysqli::errno — 返回最近函数调用的错误代码mysqli::$error_list — 返回最后命令行执行错误列表mysqli::$field_count — Returns the number of columns for the most recent querymysqli::get_charset — Returns a character set objectmysqli::$client_info — 获取 MySQL 客户端信息mysqli_get_client_version — 作为一个整数返回 MySQL 客户端的版本mysqli::get_connection_stats — 返回客户端连接的统计数据mysqli::$host_info — 返回一个表述使用的连接类型的字符串mysqli::$protocol_version — 返回 MySQL 使用的协议版本号mysqli::$server_info — 返回MySQL服务器的版本号mysqli::$server_version — 作为一个整数返回 MySQL 服务器的版本mysqli::get_warnings — Get result of SHOW WARNINGSmysqli::$insert_id — 返回最后一条插入语句产生的自增 IDmysqli::kill — 让服务器杀掉一个 MySQL 线程mysqli::more_results — 检查批量查询中是否还有查询结果mysqli::next_result — 为读取 multi_query 执行之后的下一个结果集做准备mysqli::options — 设置选项mysqli::ping — ping 一个连接,或者如果连接处于断开状态,重新连接mysqli::poll — 轮询连接mysqli::reap_async_query — 获取异步查询的结果mysqli::refresh — 刷新mysqli::release_savepoint — 从当前事务的保存点中移除一个命名保存点mysqli::rpl_query_type — 返回 RPL 查询类型mysqli::savepoint — 在当前事务中增加一个命名保存点mysqli::set_charset — 设置默认字符编码mysqli::set_local_infile_default — 取消用户指定的回调函数mysqli::set_local_infile_handler — 设置 LOAD DATA LOCAL INFILE 命令的回调函数mysqli::$sqlstate — 返回上一次 SQL 操作的 SQLSTATE 错误信息mysqli::store_result — 转移上一次查询返回的结果集mysqli::$thread_id — 返回当前连接的线程 IDmysqli::thread_safe — 返回是否是线程安全的 mysqli_stmt 预编译 SQL 语句mysqlistmt :: prepare - 准备一条 SQL 语句以便执行mysqli_stmt :: bind_param - 将变量作为参数绑定到预准备语句mysqli_stmt :: \_ construct - 构造一个新的 mysqli_stmt 对象mysqli_stmt :: $ num_rows/mysqli_num_rows() - 返回语句结果集中的行数mysqli_stmt :: $ param_count - 返回给定语句的参数个数mysqli_stmt :: $ errno - 返回最近语句调用的错误代码mysqli_stmt :: $ error_list - 返回上一个执行语句的错误列表mysqli_stmt :: $ error - 返回上一个语句错误的字符串描述mysqli_stmt :: execute - 执行准备好的 Querymysqli_stmt :: fetch - 将预准备语句的结果提取到绑定变量中mysqli_stmt :: close - 关闭准备好的语句 mysqli_stmt :: $ affected_rows - 返回上次执行的语句更改,删除或插入的总行数mysqli_stmt :: attr_get - 用于获取语句属性的当前值mysqli_stmt :: attr_set - 用于修改预准备语句的行为mysqli_stmt :: bind_result - 将变量绑定到结果存储的预准备语句mysqli_stmt :: data_seek - 寻找语句结果集中的任意行mysqli_stmt :: fetch - 将预准备语句的结果提取到绑定变量中mysqli_stmt :: $ field_count - 返回给定语句中的字段数mysqli_stmt :: free_result - 释放给定语句句柄的存储结果内存mysqli_stmt :: get_result - 从预准备语句中获取结果集mysqli_stmt :: get_warnings - 获取 SHOW WARNINGS 的结果mysqli_stmt :: $ insert_id - 获取先前INSERT操作生成的IDmysqli_stmt :: more_results - 检查多个查询是否有更多查询结果mysqli_stmt :: next_result - 从多个查询中读取下一个结果mysqli_stmt :: reset - 重置预准备语句mysqli_stmt :: result_metadata - 从预准备语句返回结果集元数据mysqli_stmt :: send_long_data - 以块为单位发送数据mysqli_stmt :: $ sqlstate - 从前一个语句操作返回 SQLSTATE 错误mysqli_stmt :: store_result - 从预准备语句中传输结果集 mysqli_result 从一个数据库查询中获取的结果集mysqli_result :: fetch_all - 将所有结果行提取为关联数组,数字数组或两者mysqli_result :: fetch_array - 将结果行提取为关联行,数字数组或两者mysqli_result :: fetch_assoc/mysqli_fetch_assoc() - 将结果行作为关联数组获取mysqli_result :: $ lengths - 返回结果集中当前行的列长度mysqli_result :: $ num_rows - 获取结果中的行数 mysqli_result :: $ current_field - 获取结果指针的当前字段偏移量mysqli_result :: data_seek - 将结果指针调整为结果中的任意行mysqli_result :: fetch_field_direct - 获取单个字段的元数据mysqli_result :: fetch_field - 返回结果集中的下一个字段mysqli_result :: fetch_fields - 返回表示结果集中字段的对象数组mysqli_result :: fetch_object - 将结果集的当前行作为对象返回mysqli_result :: fetch_row - 将结果行作为枚举数组mysqli_result :: $ field_count - 获取结果中的字段数mysqli_result :: field_seek - 将结果指针设置为指定的字段偏移量mysqli_result :: free - 释放与结果相关的内存 相关链接:mysql 学习笔记PHP & MySQL learning notes (3)PHP & MySQL learning notes (1)]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>php</tag>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[看论文了嘛]]></title>
<url>%2F2019%2F03%2F01%2Fpaper%2F</url>
<content type="text"><![CDATA[paper page test.]]></content>
<categories>
<category>paper</category>
</categories>
</entry>
<entry>
<title><![CDATA[好耶 是python -- 那些神奇的py代码]]></title>
<url>%2F2019%2F03%2F01%2Fnice-python%2F</url>
<content type="text"><![CDATA[nice python page test.]]></content>
<categories>
<category>code</category>
</categories>
</entry>
<entry>
<title><![CDATA[这周上Github了吗 -- 那些有意思的项目收集]]></title>
<url>%2F2019%2F03%2F01%2Fgithub-repo%2F</url>
<content type="text"><![CDATA[gtihub repository page test.]]></content>
<categories>
<category>code</category>
</categories>
</entry>
<entry>
<title><![CDATA[Hunger Game (饥饿游戏 原版)单词笔记]]></title>
<url>%2F2019%2F03%2F01%2Fhunger-game%2F</url>
<content type="text"><![CDATA[Chapter 15abrupt美[əˈbrʌpt] 英[əˈbrʌpt]adj. 突然的,意外的;无理的,唐突的;不连贯的;陡峭的; anticipate美[ænˈtɪsəˌpet] 英[ænˈtɪsɪpeɪt]vt. 预感;预见;预料;先于…行动;vi. 过早地提出;过早地考虑(或说、做)一件事;(在口头或用文字)预言;预测; crawl美[krɔl] 英[krɔ:l]vi. 爬行;缓慢行进;巴结;n. 缓慢的爬行;〈美俚〉跳舞,自由式游泳;养鱼(龟)池; dab美[dæb] 英[dæb]n. 少许;是…能手;做某事很在行;在某方面技术熟练;vt. (用某物)轻触;轻而快地擦掉(或抹掉);快速擦拭;(用某物)轻而快地涂上(或点上)…; damp美[dæmp] 英[dæmp]adj. 微湿的,潮湿的;消沉的,沮丧的;沉闷的;情绪低落的;n. 潮湿;消沉,失望;矿井瓦斯;有毒气体;vt. 使潮湿;使泄气,使沮丧;抑制,阻抑;使减弱;vi. [物]阻尼;减幅; desperate美[ˈdɛspərɪt] 英[ˈdespərət]adj. 绝望的;由绝望而引起的;铤而走险的,孤注一掷的;急切的,极度渴望的; dew美[du] 英[dju:]n. 水珠,露水;vt. 弄湿; dread美[drɛd] 英[dred]vt. 害怕,担心;(古语)敬畏;n. 恐惧,畏惧;令人恐惧的事物;adj. 可怕的;vi. 十分害怕; feeble美[ˈfibəl] 英[ˈfi:bl]adj. 虚弱的,衰弱的;无效的,无意的;缺乏决心的,缺乏活力的; fetal美[ˈfitl] 英[‘fi:tl]adj. 胎儿的,胎的; filthy美[ˈfɪlθi] 英[ˈfɪlθi]adj. 肮脏的,污秽的;猥亵的,淫秽的;下流的; foliage美[ˈfoʊliɪdʒ] 英[ˈfəʊliɪdʒ]n. 植物的叶子(总称),叶子及梗和枝;树叶; grin美[ɡrɪn] 英[grɪn]vi. 露齿而笑;vt. 露齿笑着表示;n. 咧嘴笑,露齿而笑; hallucination美[həˌlusəˈneʃən] 英[həˌlu:sɪˈneɪʃn]n. 幻觉,幻想;错觉; hip美[hɪp] 英[hɪp]n. 臀部;[建筑学]屋脊;臀围(尺寸);臀部…的;adj. (衣服、音乐等方面)时髦的,赶时髦的;vt. 使…的髋关节脱臼,损伤…的髋部;[建筑学]给(房屋)建屋脊;使知晓,使了解,告诉;使消息灵通; honeysuckle美[ˈhʌniˌsʌkəl] 英[ˈhʌnisʌkl]n. 忍冬,金银花; manifest美[ˈmænəˌfɛst] 英[ˈmænɪfest]vt. 显示,表明;证明;使显现;adj. 明白的,明显的;n. 货单,旅客名单; moss美[mɔs] 英[mɒs]n. 苔藓;藓沼;莫斯(男子名);泥炭沼;vt. 以苔藓覆盖;使长满苔藓;abbr. 宇载人轨道航天站; nectar美[ˈnɛktɚ] 英[ˈnektə(r)]n. 花蜜;(古希腊、罗马神话中的)众神饮的酒;琼浆玉液;甘美的饮料;adj. <古>充满美酒的,芳香甜蜜的; noxious美[ˈnɑkʃəs] 英[ˈnɒkʃəs]adj. 有害的,有毒的; onslaught美[ˈɑnslɔt] 英[ˈɒnslɔ:t]n. 猛攻,攻击;突击;大量的倾泻; orchard美[ˈɔrtʃərd] 英[ˈɔ:tʃəd]n. (通常指围起来的)果园;果园里的全部果树;<俚>棒球场; pervade美[pərˈveɪd] 英[pəˈveɪd]vt. 遍及,弥漫;渗透,充满; pluck美[plʌk] 英[plʌk]n. 勇气,精神;内脏;快而猛的拉;〈俚〉不及格;vt. 采,摘;拔掉;鼓起(勇气等);弹(乐器);vi. 拉,拽; plump美[plʌmp] 英[plʌmp]adj. 丰满的;肥胖的;丰富的;充裕的;adv. 突然地,猛地;vt&vi. (使)圆胖;(使)鼓起;(使)突然沉重地落下;n. 扑通声;〈英〉阵雨;群; prominent美[ˈprɑmɪnənt] 英[ˈprɒmɪnənt]adj. 突出的,杰出的;突起的;著名的; quench美[kwɛntʃ] 英[kwentʃ]vt. 解(渴);终止(某事物);(用水)扑灭(火焰等);将(热物体)放入水中急速冷却; rib美[rɪb] 英[rɪb]n. 肋骨;(船或屋顶等的)肋拱;肋骨状的东西;(织物的)凸条花纹;vt. 嘲笑,逗弄,开(某人的)玩笑;装肋于,给…装肋材; rinse美[rɪns] 英[rɪns]vt. 漂洗;冲洗;漂净;冲掉;n. 冲洗;染发剂;漂洗; rinse out美[rɪns aʊt] 英[rins aut]v. 冲洗掉; rot美[rɑt] 英[rɒt]n. 腐烂,腐朽;vt&vi. (使)腐烂,(使)腐朽; rotten美[ˈrɑtn] 英[ˈrɒtn]adj. 腐烂的;恶臭的;堕落的;极坏的;adv. 非常;极其; slime美[slaɪm] 英[slaɪm]n. 黏质物;黏液;黏泥;软泥;v. (用稀泥等)涂,糊;分泌黏液使黏滑;清除黏液[稀泥等];〈英俚〉滑脱,用狡猾手段脱身溜掉(away through etc.); soot美[sʊt, sut] 英[sʊt]n. 煤烟,烟灰;油烟;v. 煤烟弄脏;弄得尽是煤烟; splash美[splæʃ] 英[splæʃ]vt. 使(液体)溅起;vi. (指液体)溅落;n. (光、色等的)斑点;溅泼声;溅上的斑点;溅泼的量; stiff美[stɪf] 英[stɪf]adj. 严厉的;僵硬的,坚硬的;呆板的,拘谨的;顽固的;adv. <口>极度地,非常;n. 死尸;笨蛋,傻瓜;流动工人;吝啬鬼穷光蛋;vt. 诈骗;失信; stretch美[strɛtʃ] 英[stretʃ]v. 伸展;延伸;持续;包括;n. 伸展;弹性;一片;一段时间;adj. 可伸缩的;弹性的; strip down美[strɪp daʊn] 英[strip daun]脱光衣服; swell美[swɛl] 英[swel]vt&vi. 增强;肿胀;膨胀;充满(激情);n. 汹涌;重要人士;(尤指身体部位)凸起的形状;声音渐强;adj. 极好的;了不起的;非常棒的; swollen美[ˈswolən] 英[ˈswəʊlən]adj. 膨胀的;肿起的;涨满的;v. 增强,肿胀,鼓起(swell 的过去式和过去分词); tangle美[ˈtæŋɡəl] 英[ˈtæŋgl]n. 纠缠,纠纷;混乱,慌乱;昏乱的状态;争论;vt&vi. (使)缠结,(使)乱作一团;使陷入,捕获;使纠纷;参加辩论、争执或冲突; tentative美[ˈtɛntətɪv] 英[ˈtentətɪv]adj. 试探性的;试验的;尝试性的;不确定的;n. 假设;实验;尝试; tread美[trɛd] 英[tred]vi. 踩,踏;行走;交尾;vt. 踩成;踏出;步行于;踩(烂);n. 踏,踩,走;交尾;(楼梯的)踏板;轮胎接触地面的部分; twig美[twɪɡ] 英[twɪg]n. 细枝,嫩枝;v. 理解,明白; vein美[ven] 英[veɪn]n. 静脉;[地]矿脉,岩脉;[植]叶脉;气质,倾向;v. 使有脉络;使有纹理;象脉络般分布于; venom美[ˈvɛnəm] 英[ˈvenəm]n. (某些蛇、蝎子等分泌的)毒液;恶意;<古>毒物;v. 放毒; wholly美[ˈhoʊlli] 英[ˈhəʊlli]adv. 完全地,全部地;十足,统统;专门;一并;]]></content>
<categories>
<category>language-learning</category>
</categories>
</entry>
<entry>
<title><![CDATA[session_cookie]]></title>
<url>%2F2019%2F02%2F28%2Fsession-cookie%2F</url>
<content type="text"><![CDATA[Cookie 和 Session 都是会话技术Cookie 是运行在客户端,Session 是运行在服务器端浅谈一下 Session 与 Cookie 之间的区别和联系 SessionSession 是服务器端使用的一种记录客户端状态的机制,客户端(浏览器)访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上。 步骤 客户端(浏览器)发送请求 服务器端生成 Session 和一个 Session ID 来作为这个 Session 的唯一标识,将 Session ID 发送到客户端 客户端第二次发送请求,将前一次响应的 Session ID 一并发送 服务器端从请求中提取出 Session ID,和保存的所有 Session ID 进行对比,找到对应的 Session,如果该 Session 已经被销毁,生成新的 Session 服务器端如果保存 Session 超出时间限制会销毁 Session Session 的生命周期Session 保存在服务器端,为了获得更高的存取速度,服务器一般把 Session 放在内存里。 如果 Session 内容过于复杂,当大量客户访问服务器时可能会导致内存溢出。因此,Session 里的信息应该尽量精简。 Session 生成后,只要用户继续访问,服务器就会更新 Session 的最后访问时间,并维护该 Session。 随着用户访问服务器,Session 会越来越多。为防止内存溢出,服务器会把长时间内没有活跃的 Session 从内存删除。 Session 的用法(不详细展开)void setAttribute(String attribute, Object value)设置 Session 属性removeAttribute(String attribute)移除 Session 属性getLastAccessedTime()返回 Session 的最后活跃时间getMaxInactiveInterval()返回 Session 的超时时间void invalidate()使该 Session 失效 CookieCookie 技术是客户端的解决方案,由服务器端发给客户端的特殊信息会以文本文件的方式存放在客户端,然后客户端每次向服务器发送请求的时候都会带上这些特殊的信息。 步骤 用户使用客户端(浏览器)访问,提供个人信息并且提交至服务器 服务器在向客户端回传的同时发回个人信息,存放于 HTTP 响应头 当客户端(浏览器)接收到来自服务器的响应之后,浏览器会将这些信息存放在 cookie 文件夹下,然后再向服务器发送请求,把相应的 Cookie 再次发回至服务器。信息则存放在 HTTP 请求头 服务器端在接收到来自客户端浏览器的请求,通过分析存放于请求头的 Cookie 得到客户端特有的信息,从而动态生成与该客户端相对应的内容 Cookie 的有效期Cookie 的 maxAge 决定着 Cookie 的有效期,单位为秒(Second)Cookie 会在 maxAge 秒之后自动失效 Cookie 的属性String name:该 Cookie 的名称Object value:该 Cookie 的值int maxAge:该 Cookie 失效的时间,单位秒boolean secure:该 Cookie 是否仅被使用安全协议传输String domain:可以访问该 Cookie 的域名String comment:该 Cookie 的用处说明 difference & connection区别 cookie 数据存放在客户的浏览器上,session 数据放在服务器上 cookie 不是很安全,别人可以分析存放在本地的 COOKIE 并进行 COOKIE 欺骗,考虑到安全应当使用 session; session 会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能。考虑到减轻服务器性能方面,应当使用 COOKIE; 单个 cookie 在客户端的限制是 3K,就是说一个站点在客户端存放的 COOKIE 不能超过 3K; 联系 服务端执行 session 机制时候会生成 session 的 id 值,这个 id 值会发送给客户端,客户端每次请求都会把这个 id 值放到 http 请求的头部发送给服务端,而这个 id 值在客户端会保存下来,保存的容器就是 cookie]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>session</tag>
<tag>cookie</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Laravel SQL migration]]></title>
<url>%2F2019%2F02%2F27%2Fmigration%2F</url>
<content type="text"><![CDATA[结合 Laravel 的 Schema 构建器构建应用的数据库表结构,类似于数据库的版本控制,允许团队成员间编辑并共享应用的数据库表结构Laravel 的 Schema 门面提供了与数据库系统无关的创建和操纵表的支持,在 Laravel 所支持的所有数据库系统中提供一致的、优雅的、流式的 API,将 SQL 转成 PHP 去执行 部署环境(WAMP)php 7.3.1composer 1.8.4laravel 5.8.0MySQL 5.7.24 迁移步骤 MySQL 数据库创建 Database 到 laravel 目录下修改.env文件符合数据库配置 DB_CONNECTION=mysqlDB_HOST=127.0.0.1DB_PORT=3306DB_DATABASE=your_database_nameDB_USERNAME=rootDB_PASSWORD= 到 laravel 目录创建新的迁移php artisan make:migration create_table_name创建的数据表在laravel\database\migration目录下 --table和--create选项可以用于指定表名以及该迁移是否要创建一个新的数据表。这些选项只需要简单放在上述迁移命令后面并指定表名php artisan make:migration create_users_table --create=usersphp artisan make:migration add_votes_to_users_table --table=users 编写迁移数据表迁移类包含了两个方法:up和down。up方法用于新增表,列或者索引到数据库,而down方法就是up方法的反操作用到 Laravel 的schema构建器来创建和修改表,后面给出具体实现方法 运行迁移表到数据库php artisan migrate 强制运行这些命令而不被提示,可以使用—force(不推荐)php artisan migrate --force 在 MySQL 中可以看到 Database 下有新的表 执行回滚 在 Database 下有 migration 表,使得 laravel 可以回滚 执行文件中的public function down(),回滚最后一批运行的迁移php artisan migrate:rollback回滚所有的应用迁移php artisan migrate:reset先回滚所有数据库迁移php artisan migrate:refresh回滚或重建指定数量的迁移,refresh 命令提供的 step 选项php artisan migrate:refresh --step=5 在迁移之前进行试验php artisan migrate --pretend 创建表使用 Schema 门面上的 create 方法来创建新的数据表。create 方法接收两个参数,第一个是表名,第二个是获取用于定义新表的 Blueprint 对象的闭包Schema::create('table_name', function (Blueprint $table){ }) 创建表中的列在 Schema 中创建表中的列结构 $table->类型('名称'); 常用属性 $table->bigIncrements('id'); //自增ID,类型为bigint$table->bigInteger('votes'); //等同于数据库中的BIGINT类型$table->binary('data'); //等同于数据库中的BLOB类型$table->boolean('confirmed'); //等同于数据库中的BOOLEAN类型$table->char('name', 4); //等同于数据库中的CHAR类型$table->date('created_at'); //等同于数据库中的DATE类型$table->dateTime('created_at'); //等同于数据库中的DATETIME类型$table->dateTimeTz('created_at'); //等同于数据库中的DATETIME类型(带时区)$table->decimal('amount', 5, 2); //等同于数据库中的DECIMAL类型,带一个精度和范围$table->double('column', 15, 8); //等同于数据库中的DOUBLE类型,带精度, 总共15位数字,小数点后8位.$table->enum('choices', ['foo', 'bar']); //等同于数据库中的 ENUM类型$table->float('amount'); //等同于数据库中的 FLOAT 类型$table->increments('id'); //数据库主键自增ID$table->integer('votes'); //等同于数据库中的 INTEGER 类型$table->ipAddress('visitor'); //等同于数据库中的 IP 地址$table->json('options'); //等同于数据库中的 JSON 类型$table->jsonb('options'); //等同于数据库中的 JSONB 类型$table->longText('description'); //等同于数据库中的 LONGTEXT 类型$table->macAddress('device'); //等同于数据库中的 MAC 地址$table->mediumIncrements('id'); //自增ID,类型为无符号的mediumint$table->mediumInteger('numbers'); //等同于数据库中的 MEDIUMINT类型$table->mediumText('description'); //等同于数据库中的 MEDIUMTEXT类型$table->morphs('taggable'); //添加一个 INTEGER类型的 taggable_id 列和一个 STRING类型的 taggable_type列$table->nullableTimestamps(); //和 timestamps()一样但允许 NULL值.$table->rememberToken(); //添加一个 remember_token 列: VARCHAR(100) NULL.$table->smallIncrements('id'); //自增ID,类型为无符号的smallint$table->smallInteger('votes'); //等同于数据库中的 SMALLINT 类型$table->softDeletes(); //新增一个 deleted_at 列 用于软删除.$table->string('email'); //等同于数据库中的 VARCHAR 列 .$table->string('name', 100); //等同于数据库中的 VARCHAR,带一个长度$table->text('description'); //等同于数据库中的 TEXT 类型$table->time('sunrise'); //等同于数据库中的 TIME类型$table->timeTz('sunrise'); //等同于数据库中的 TIME 类型(带时区)$table->tinyInteger('numbers'); //等同于数据库中的 TINYINT 类型$table->timestamp('added_on'); //等同于数据库中的 TIMESTAMP 类型$table->timestampTz('added_on'); //等同于数据库中的 TIMESTAMP 类型(带时区)$table->timestamps(); //添加 created_at 和 updated_at列$table->timestampsTz(); //添加 created_at 和 updated_at列(带时区)$table->unsignedBigInteger('votes'); //等同于数据库中无符号的 BIGINT 类型$table->unsignedInteger('votes'); //等同于数据库中无符号的 INT 类型$table->unsignedMediumInteger('votes'); //等同于数据库中无符号的 MEDIUMINT 类型$table->unsignedSmallInteger('votes'); //等同于数据库中无符号的 SMALLINT 类型$table->unsignedTinyInteger('votes'); //等同于数据库中无符号的 TINYINT 类型$table->uuid('id'); //等同于数据库的UUID 常用约束 ->after('column') //将该列置于另一个列之后 (仅适用于MySQL)->comment('my comment') //添加注释信息->default($value) //指定列的默认值->first() //将该列置为表中第一个列 (仅适用于MySQL)->nullable() //允许该列的值为NULL->storedAs($expression) //创建一个存储生成列(只支持MySQL)->unsigned() //设置 integer 列为 UNSIGNED->virtualAs($expression) //创建一个虚拟生成列(只支持MySQL) 格式示例 class CreateTableName extends Migration{/** * Run the migrations. * * @return void*/public function up(){ Schema::create('table_name', function (Blueprint $table) { $table->bigIncrements('id'); $table->string('name'); $table->string('email')->unique(); $table->timestamp('email_verified_at')->nullable(); $table->string('password'); $table->rememberToken(); $table->timestamps(); });}/** * Reverse the migrations. * * @return void*/public function down(){ Schema::dropIfExists('table_name');} 修改、重命名、删除列->change()方法允许你修改已存在的列为新的类型,或者修改列的属性->renameColumn()方法可以重命名一个列->dropColumn方法可以删除列 Schema::table('users', function ($table) { $table->string('name', 50)->change(); //name列的尺寸从 25 增加到 50 $table->renameColumn('from', 'to'); //重命名 from 为 to $table->dropColumn('votes'); //删除一个列 $table->dropColumn(['votes', 'avatar', 'location']); //删除多个列}); 需要添加 doctrine/dbal 依赖到 composer.json 文件 暂不支持 enum 类型的列的修改和重命名 添加索引键$table->primary('id'); //添加主键索引$table->primary(['first', 'last']); //添加混合索引$table->unique('email'); //添加唯一索引$table->unique('state', 'my_index_name'); //指定自定义索引名称$table->index('state'); //添加普通索引 删除索引$table->dropPrimary(' '); //删除主键索引$table->dropUnique(' '); //删除唯一索引$table->dropIndex(' '); //删除普通索引 外键约束(loading…)检查列表是否存在使用 hasTable 和 hasColumn 方法检查表或列是否存在 if (Schema::hasTable('users')) { //}if (Schema::hasColumn('users', 'email')) { //} 设置表的存储引擎,在 schema 构建器上设置 engine 属性Schema::create('users', function ($table) { $table->engine = 'InnoDB'; $table->increments('id');}); 重命名/删除表在public function up()中添加Schema::rename('your_table_name','change_name');更新public function down()中的表名 在public function down()中添加Schema::drop('users'); 或 Schema::dropIfExists('users');用于迁移的回滚 参考:Laravel 数据库迁移Database Migration]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>laravel</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mysql like子句和正则表达式匹配]]></title>
<url>%2F2019%2F02%2F23%2Fmysql-regular%2F</url>
<content type="text"><![CDATA[-基础笔记-MySQL like 子句和正则表达式的使用MySQL 可以通过 LIKE …% 来进行模糊匹配,也可以使用 REGEXP 操作符来进行正则表达式匹配 LIKE当需要获取 WHERE 字段中包含的匹配记录,就需要在 WHERE 子句中使用 LIKE 子句WHERE 子句中可以使用 = 来设定获取数据的条件,LIKE 子句中使用百分号 % 字符来表示任意字符.如果没有使用 %, LIKE子句与 = 的效果是一样的可以使用 AND 或者 OR 指定一个或多个条件,可以在 DELETE 或 UPDATE 命令中使用 WHERE...LIKE 子句来指定条件 SELECT field1, field2,...fieldNFROM table_nameWHERE field1 LIKE `condition` [AND [OR]] filed2 = 'somevalue' 与 WHERE 条件结合'%a' //以a结尾的数据'a%' //以a开头的数据'%a%' //含有a的数据'_a_' //三位且中间字母是a的'_a' //两位且结尾字母是a的'a_' //两位且开头字母是a的 正则表达式MySQL 正则模式可应用于 REGEXP 操作符中MySQL 中正则表达式匹配不区分大小写,如希望区分大小写,可使用 binary 关键字 模式 描述 ^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 ‘\n’ 或 ‘\r’ 之后的位置。 $ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的 Multiline 属性,$ 也匹配 ‘\n’ 或 ‘\r’ 之前的位置。 . 匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式。 [...] 字符集合。匹配所包含的任意一个字符。例如, ‘[abc]’ 可以匹配 “plain” 中的 ‘a’。 [^...] 负值字符集合。匹配未包含的任意字符。例如, ‘abc‘ 可以匹配 “plain” 中的’p’。 `p1 p2 p3` 匹配 p1 或 p2 或 p3。例如,’z food’ 能匹配 “z” 或 “food”。’(z f)ood’ 则匹配 “zood” 或 “food”。 * 匹配前面的子表达式零次或多次。例如,zo 能匹配 “z” 以及 “zoo”。 等价于{0,}。 + 匹配前面的子表达式一次或多次。例如,’zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等价于 {1,}。 {n} n 是一个非负整数。匹配确定的 n 次。例如,’o{2}’ 不能匹配 “Bob” 中的 ‘o’,但是能匹配 “food” 中的两个 o。 {n,m} m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。 示例任意字母数字:[a-zA-Z0-9]任意十六进制:[a-fA-F0-9]任意字符:[a-zA-Z]空格和制表符:[\t]任意空白字符:[\f\n\r\t\v] (换页\换行\回车\制表\纵向制表)x OR y:”x|y”email:”@163[.,]com$“x 至少出现一次,最多出现三次:”x{1,3}”]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[时间序列分析中的资金流入流出问题]]></title>
<url>%2F2019%2F02%2F20%2Ffund-flow%2F</url>
<content type="text"><![CDATA[-服务外包项目-资金流入流出问题的研究笔记,数据来自蚂蚁金服大数据赛题笔记持续更新中 研究现状资金流入流出问题 时间序列模型分析:启动时间短,训练数据量不大,成本低自回归算法 AR:呈现过去时刻对预测的直接影响移动平均算法 MA:预测意料之外的事自回归+移动平均 ARMA:综合以上的平衡齐次非平稳 ARIMA:针对非平稳序列 时间序列可较好的预测短期价格变动,时期增长会导致误差率增高 投资分析:长期分析法,利用经济学角度分析内在价值 基本分析:宏观经济分析,行业分析和公司分析应用不够直观,市场反应不够敏锐 技术分析:根据图标信息,技术指标记录推断变化趋势技术指标滞后,无法把控整体趋势 混沌动力学 神经网络利用探索数据间的交叉关系建立模型契合资金波动的高度非线性特点 定性预测:专家意见,德尔菲法 因果预测:回归分析,定性和定量分析 组合算法 统计学+机器学习 灰色系统+神经网络 时间序列+神经网络 集成学习 ensemble learning 串行思路:采用串行的方式生成多个学习器目的在于减少偏差(bias),使用多个弱分类器组合成为一个强分类器,代表算法 Bagging,boosting,GBDT 并行思路:通过使用并行的学习,得到多个学习模型然后取其平均结果目的在于减少方差,代表算法 Random Forest 因子分解机 Factorization Machine (loading…)通过特征向量去模拟因子分解模型,利用特征抽取的方法构造出特征并借助因子分解模型对不同变量间的相互作用进行建模 FM 算法常用来解决二分类,回归,排序问题 模型构建数据集—>数据预处理—>特征抽取—>预测算法设计—>误差分析—>优化 数据预处理:剔除异常值,表格间数据集成特征抽取:时间特征,用户特征,利率特征预测算法设计(loading…)误差分析:用均方根误差评价 数据预处理余额宝用户数据基本信息数据 user_profile: 列名 类型 含义 示例 user_id bigint 用户 ID 1234 Sex bigint 用户性别( 1 :男, 0:女 ) 0 City bigint 所在城市 6081949 constellation string 星座 射手座 申购赎回数据 user_balance: 列名 类型 含义 示例 user_id bigint 用户 id 1234 report_date string 日期 20140407 tBalance bigint 今日余额 109004 yBalance bigint 昨日余额 97389 total_purchase_amt bigint 今日总购买量 = 直接购买 + 收益 21876 direct_purchase_amt bigint 今日直接购买量 21863 purchase_bal_amt bigint 今日支付宝余额购买量 0 purchase_bank_amt bigint 今日银行卡购买量 21863 total_redeem_amt bigint 今日总赎回量 = 消费 + 转出 10261 consume_amt bigint 今日消费总量 0 transfer_amt bigint 今日转出总量 10261 tftobal_amt bigint 今日转出到支付宝余额总量 0 tftocard_amt bigint 今日转出到银行卡总量 10261 share_amt bigint 今日收益 13 category1 bigint 今日类目 1 消费总额 0 category2 bigint 今日类目 2 消费总额 0 category3 bigint 今日类目 3 消费总额 0 category4 bigint 今日类目 4 消费总额 0 收益率数据 mfd_day_share_interest: 列名 类型 含义 示例 mfd_date string 日期 20140102 mfd_daily_yield double 万份收益,即 1 万块钱的收益。 1.5787 mfd_7daily_yield double 七日年化收益率( % ) 6.307 银行拆借利率数据 mfd_bank_shibor: 列名 类型 含义 示例 mfd_date String 日期 20140102 Interest_O_N Double 隔夜利率(%) 2.8 Interest_1_W Double 1 周利率(%) 4.25 Interest_2_W Double 2 周利率(%) 4.9 Interest_1_M Double 1 个月利率(%) 5.04 Interest_3_M Double 3 个月利率(%) 4.91 Interest_6_M Double 6 个月利率(%) 4.79 Interest_9_M Double 9 个月利率(%) 4.76 Interest_1_Y Double 1 年利率(%) 4.78 数据关系今日余额 = 昨日余额 + 今日申购 - 今日赎回今日余额 = 昨日余额 + [直接购买(支付宝+银行)+ 收益] - [消费 + 支出(支付宝+银行)]tBalance = yBalance + (direct_purchase_amt + share_amt) - (consume_amt + transfer_amt) 抽取特征资金流预测采用时间序列预测的 ARIMA 模型,BP 神经网络,集成学习来进行预测,并结合不同的算法进行组合预测 ARIMABPARIMA+BPGBDTRandom Forest]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>time_series</tag>
<tag>ensemble_learning</tag>
<tag>bp_nn</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Pandas 数据整合、清洗和SQL比较]]></title>
<url>%2F2019%2F02%2F19%2Fpandas%20compare%20with%20SQL%2F</url>
<content type="text"><![CDATA[some examples of how various SQL operations would be performed using pandas收集和比较 pandas 使用过程中和数据库类似的一些操作,方便使用 pandas 进行数据分析 import pandas and NumPy as follows import numpy as npimport pandas as pd attributions of DataFrame df.dtypes # data type of columnsdf.index # indexesdf.columns # return pandas.indexdf.values # return values of each rowdf.shape # return dimensionality of df 列的修改操作-- addALTER TABLE tipADD column_name NULL--updateUPDATE tipsSET tip = tip*2WHERE tip < 2;--deleteDELETE FROM tipsWHERE tip > 9;--distinct 去重SELECT DISTINCT timeFROM tips 添加tip['new_col'] = [value1,value2 ...]// 直接添加列tip.assign(new_col = func)// 通过 assign 使用赋值函数添加tip.loc[df.col==value, 'new_col'] = 'new_value'// 通过索引到行单独添加 更新tips.loc[tips['tip'] < 2, 'tip'] *= 2// 通过条件筛选出列来直接更新 删除tips = tips.drop(tips['tip']>9, axis=1)tips = tips.loc[tips['tip'] <= 9]Pandas 可以把不需要的过滤掉而不是删除 去重tip[tip.duplicated()]// 查看重复的数据tips.drop_duplicates(subset=['time'], keep='last', inplace=True)// subset 选定列// keep {‘first’,’last’,False}, 保留重复元素中的第一个、最后一个,或全部删除// inplace 是否在原对象基础上进行修改 排序sort_value('col_name', ascending=True, na_position='last')sort_value(['col_name1', 'col_name2'], ascending=True, na_position='last')// ascending 设定升降序,na_position 决定 缺失值排列的位置 sort_index('col_name')可对索引进行排序 select 查找SELECT 'name_1', 'name_2', ...FROM tipsLIMIT 5; SELECT * = tips 不列举列名,显示所有列tips[['name_1','name_2' ...]].head(5) pandas 中利用列名和 head()进行筛选 df.loc[1:3, ['name_1,'name_2','name_3' ...]] 基于列 label,可选取特定行(根据行 index)df.iloc[1:3, [0,1,3,5,...]] 基于 position(行/列)的位置ix 为 loc 与 iloc 的混合体,既支持 label 也支持 positiondf.at[3, 'name'] 根据指定行 index 及列 label,快速定位 DataFrame 的元素;iat 与 at 类似,不同的是根据 position 来定位的; whereSELECT *FROM tipsWHERE time = 'Dinner'LIMIT 5;-- tips of more than $5.00 at Dinner mealsSELECT *FROM tipsWHERE time = 'Dinner' AND tip > 5.00;-- tips of more than 5 sizes or more than 45 total_billSELECT *FROM tipsWHERE size >= 5 OR total_bill > 45;SELECT *FROM tipsWHERE total_bill in 20;SELECT *FROM tipsWHERE total_bill not in 20,22,24;SELECT *FROM frameWHERE col2 IS NULL;SELECT *FROM frameWHERE col1 IS NOT NULL; tips[tips['time'] == 'Dinner'].head(5) 最直观的是使用布尔索引 tips[(tips['time'] == 'Dinner') & (tips['tip'] > 5.00)]tips[(tips['size'] >= 5) | (tips['total_bill'] > 45)]tips[tips['total_bill].isin([20])]tips[-tips['total_bill].isin([20,22,24])]搭配 and, or, in, not 关键词可用 & | isin() 实现查询两者之间记录可以使用between(5, 40, inclusive=True) frame[frame['col2'].isna()/isnull()]frame[frame['col1'].notna()/isnull()==False]搭配 NULL, NOT NULL,Pandas 中使用 isna() notna() 或 isnull()==True/False 实现 可以使用str.contains()进行正则表达式匹配查询 可以使用 pandas 提供的query()方法完成指定条件查询tips.query('指定条件') group bydf.groupby(['group_name'])[['col1, col2 ...]].max/min/mean/median/std/count/size()// col_name 作为分组变量,对之后给出的统计量进行分组 SELECT sex, count(*)FROM tipsGROUP BY sex;-- Female 87 Male 157 tips.groupby('sex').size()//groupby()将数据集拆分为组,应用一些函数(通常是聚合),然后将这些组组合在一起 ips.groupby('sex')['total_bill'].count()//可以使用 count()返回特定列中的非空记录数 SELECT day, AVG(tip), COUNT(*)FROM tipsGROUP BY day;/*Fri 2.734737 19Sat 2.993103 87Sun 3.255132 76Thur 2.771452 62...*/SELECT smoker, day, COUNT(*), AVG(tip)FROM tipsGROUP BY smoker, day; tips.groupby('day').agg({'tip': np.mean, 'day': np.size})//agg()可以使用字典格式描述列,一次汇总多个统计量 tips.groupby(['smoker', 'day']).agg({'tip': [np.size, np.mean]})//groupby()支持多条件 对分组之后的数据表可以使用多重索引的方式进行索引df['group_name']['col_name'] groupby 其它操作df.groupby(['tips']).groups // 查看分组对象df.groupby(['tips']).get_group('day') // 得到某一个分组df.groupby(['tips']).transform(lambda x: ...) // 对分组数据进行 lambda 公式转换df.groupby(['tips']).filter(filter_func) // 带数据过滤的分组,filter 函数单独书写for group in df.groupby(['tips']):print (group) // 迭代输出分组内容 数据透视表pd.pivot_table函数用来探索数据集内部的关联性,可实现拆分和堆叠列;数据透视表更像是一种多维的 GroupBy 累计操作。 拆分pd.pivot_table(table, index='id', columns='type', values='value', fill_value='0', aggfunc='sum').reset_index()// index 原数据中用于分组的列或键,作为新表的行// columns 新数据表中变量所在的列,作为新表的列// values 待拆分的列// fill_value 替换缺失值// aggfunc 聚合函数或函数列表 堆叠pd.melt(table, id_vars='id', value_vars=['value1','value2' ...], value_name='name', var_name='type')// id_vars 用于标示的变量// value_vars 用于堆叠的变量// value_type 堆叠后变量的名称// value_name 堆叠后值的名称 join-- inner joinSELECT *FROM df1INNER JOIN df2 ON df1.key = df2.key;-- left join: show all records from df1SELECT *FROM df1LEFT OUTER JOIN df2 ON df1.key = df2.key;-- right join: show all records from df1SELECT *FROM df1LEFT OUTER JOIN df2 ON df1.key = df2.key;-- full join: show all records from both tablesSELECT *FROM df1FULL OUTER JOIN df2 ON df1.key = df2.key; JOINs can be performed with join() or merge()pd.merge(df1, df2, on='key')pd.merge(df1, df2, on='key', how='left')pd.merge(df1, df2, on='key', how='right')pd.merge(df1, df2, on='key', how='outer') 可以设置关键字匹配索引:pd.merge(df1, df2.set_index('key'), on='key', right_index=True) full join 在 RDBMS(关系型数据库)里不适用 unionSELECT city, rankFROM df1UNION ALLSELECT city, rankFROM df2;/* city rank Chicago 1San Francisco 2New York City 3 Chicago 1 Boston 4 Los Angeles 5*/ pd.concat([df1, df2]) // concat()用于链接两个数据表内容pd.concat([df1, df2], axis=1) // axis=1 进行横向合并pd.concat([df1, df2]).drop_duplicates() // 可以移除重复行 order and aggregateSELECT * FROM tipsORDER BY tip DESCLIMIT 10 OFFSET 5; tips.nlargest(10 + 5, columns='tip').tail(10) // 根据 tip 降序排序,从最小 5 开始输出 10 个结果 -- Oracle's ROW_NUMBER() analytic functionSELECT * FROM ( SELECT t.*, ROW_NUMBER() OVER(PARTITION BY day ORDER BY total_bill DESC) AS rn FROM tips t)WHERE rn < 3ORDER BY day, rn; ROW_NUMBER() OVER (PARTITION BY COL1 ORDER BY COL2)row_number 从 1 开始,为每一条分组记录返回一个数字,根据 COL1 分组,在分组内部根据 COL2 排序,而此函数计算的值就表示每组内部排序后的顺序编号(组内连续的唯一的)MySQL 本身不含row_number()函数 tips.assign(rn=tips.sort_values(['total_bill'], ascending=False) .groupby(['day']) .cumcount() + 1) .query('rn < 3') .sort_values(['day', 'rn']) // DataFrame.assign()整理出一个新的列// sort_values([‘total_bill’], ascending=False 根据 total_bill 的值倒叙排序,赋值 rn// groupby([‘day’]) 根据 day 聚合// query(‘rn < 3’) 筛选 rn<3 的行// sort_values([‘day’, ‘rn’] 根据 day 和 rn 排序 tips.assign(rnk=tips.groupby(['day'])['total_bill'] .rank(method='first', ascending=False)) .query('rnk < 3') .sort_values(['day', 'rnk']) // 使用 rank 函数返回从小到大排序的下标 SELECT * FROM ( SELECT t.*, RANK() OVER(PARTITION BY sex ORDER BY tip) AS rnk FROM tips t WHERE tip < 2)WHERE rnk < 3ORDER BY sex, rnk; tips[tips['tip'] < 2] .assign(rnk_min=tips.groupby(['sex'])['tip'] .rank(method='min')) .query('rnk_min < 3') .sort_values(['sex', 'rnk_min']) 数据清洗 使用 df.drop_duplicated() 去除重复的数据 使用 df.apply(lambda col:sum(col.isnull())) 计算每列缺失的数据 使用 df.col.fillna(df.col.mean/median()) 填补缺失值 使用盖帽法,分箱法,聚类法去除噪声 盖帽法 def cap(x,quantile=[0.01,0.99]): # 生成分位数 Q01,Q99 = x.quantile(quantile).values.tolist() if Q01 > x.min(): x = x.copy() x.loc(x<Q01) = Q01 if Q99 < x.max(): x = x.copy() x.loc(x>Q99) = Q99new_df = df.apply(cap, quantile=[0.01, 0.99]) 分箱法等深分箱:每个分箱中样本数量一致df.cut(df.col, bins=df.col.quantile([0, 0.25, 0.5, 0.75, 1]))// 利用分位数找到分割点进行 4 等分箱 等宽分箱:每个分箱中取值范围一致pd.cut(pd.col, 5)// 根据列将数据分成 5 等分 聚类法多用于多变量处理,常用的有 k-means 聚类]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>python</tag>
<tag>pandas</tag>
</tags>
</entry>
<entry>
<title><![CDATA[book-list (2018)]]></title>
<url>%2F2019%2F02%2F16%2Fbook-list-2018%2F</url>
<content type="text"><![CDATA[个人书库,收集正在看的和准备要看的好书,不定期更新 【2018 年《华盛顿邮报》推荐书单】本年度推荐的书:《Good Aand Mad》(《善良与狂暴》)、《The Library Book》(图书馆的书)、《The line becomes a river》(《一条线变成一条河》)、《The maze at Windermere》(《温德米尔的迷宫》)、《On desperate ground》(《在绝望的战场上》)、《One person,no vote》(《一人,零票》)、《The Overstory》(《上层林冠》)、《A place for US》(《属于我们的地方》)、《There There》(《好了,没事了》)、《Washington Black》(《华盛顿黑人》) 【2018 年《华尔街日报》十佳书单】本年度推荐的书:《不对称》(ASYMMETRY)《丘吉尔传》(CHURCHILL)《暴风骤雨》(CLOUDBURSTS)《意识的本能》(THE CONSCIOUSNESS INSTINCT)《弗雷德里克·道格拉斯传》(FREDERICK DOUGLASS)《天赐良机》(GODSEND)《伊庇鲁斯的挽歌》(LAMENT FROM EPIRUS)《我自己的生活》(A LIFE OF MY OWN)《头号爱国者》(PATRIOT NUMBER ONE)《暗影季节》(SEASON OF THE SHADOW) 【2018《金融时报》和麦肯锡年度“最佳商业图书奖”入围书单 】本年度推荐的书:《美国资本主义》(Capitalism in America)《崩溃》(Crashed)《短命的银行》(The Bank That Lived A Little)《受损的商品》(Damaged Goods)《滴血成金》(Bad Blood)《十亿美元鲸鱼》(Billion Dollar Whale):《简斯维尔》(Janesville),《认清事实》(Factfulness):《万物价值》(The Value of Everything)《给人民发钱》(Give People Money)《新势力》(New Power)《零工》(Gigged)《亿万富翁的天下》(The Billionaire Raj)《崛起的五千万》(Fifty Million Rising)《极乐男权》(Brotopia)《谁是迈克尔·奥维茨?》(Who Is Michael Ovitz?) 【2018 年比尔·盖茨推荐的 5 本书】本年度推荐的书:《21 世纪的 21 一个教训 21 Lessons for the 21st Century》《一扫光的武器 Army of None_ Autonomous Weapons and the Future of War》《Educated 》《Bad Blood》《Meditation and Mindfulness》 【《经济学人》2018 年推荐书单】《Moneyland》《Enlightenment Now》《Fascism: A Warning》《First Raise a Flag》《Into the Hands of the Soldiers》《Shadows of Empire》《A History of America in 100 Maps》《Pogrom》《The China Mission》《Rise and Kill First》《We the Corporations》《AI Superpowers》《Radical Markets》《EuroTragedy》《Crashed》《The Wife’s Tale: A Personal History》《Educated》《Barracoon》《Napoleon: A Life》《Churchill: Walking with Destiny》《Gandhi》《The Spy and the Traitor》 【彭博盘点 2018 年书单】《high growth handbook》《The Coddling of the American Mind: How Good Intentions and Bad Ideas Are Setting Up a Generation for Failure》《Our Towns: A 100,000-Mile Journey Into the Heart of America》《Educated: A Memoir》《Stubborn Attachments: A Vision for a Society of Free, Prosperous, and Responsible Individuals》《Refugee》《Factfulness: Ten Reasons We’re Wrong About the World—and Why Things Are Better Than You Think》《The Efficiency Paradox: What Big Data Can’t Do》《The Third Plate: Field Notes on the Future of Food》《Inspired: How to Create Tech Products Customers Love》《Bad Blood: Secrets and Lies in a Silicon Valley Startup》《Grant》《Principles: Life and Work》《The Coddling of the American Mind: How Good Intentions and Bad Ideas Are Setting Up a Generation for Failure》《The Culture Code: The Secrets of Highly Successful Groups》《Hit Refresh: The Quest to Rediscover Microsoft’s Soul and Imagine a Better Future for Everyone》《Keeping At It: The Quest for Sound Money and Good Government》《New Power: How Power Works in Our Hyperconnected World—and How to Make It Work for You》《The Complete Personal Memoirs of Ulysses S. Grant》《The Book of Why: The New Science of Cause and Effect》《Powerful: Building a Culture of Freedom and Responsibility》《The Courage to Be Disliked: The Japanese Phenomenon That Shows You How to Change Your Life and Achieve Real 》《Happiness》《Dare to Lead: Brave Work. Tough Conversations. Whole Hearts.》《Without Precedent: Chief Justice John Marshall and His Times》《The Largesse of the Sea Maiden: Stories》《Paris in the Present Tense》《Destined for War: Can America and China Escape Thucydides’s Trap?》《Small Fry》《Life 3.0: Being Human in the Age of Artificial Intelligence》《Love and Ruin》]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>book</tag>
</tags>
</entry>
<entry>
<title><![CDATA[mysql 学习笔记]]></title>
<url>%2F2019%2F02%2F15%2Fmysql%2F</url>
<content type="text"><![CDATA[-基础笔记-二次回顾,学校课程 + 慕课网 MySQL 详细学习笔记包括 MySQL 架构,MySQL 操作,数据类型,数据库操作,数据表操作(创增删改查排序分组)及子句操作 相关术语DB:数据库(Database)DBS:数据库系统(Database System)DBMS:数据库管理系统(Database Management System) SQL 语言: DDL 数据定义语言 DML 数据操作语言 DQL 数据查询语言 DCL 数据控制语言 MySQL 架构MySQL 是由 SQL 接口、解析器、优化器、缓存和存储引擎组成 Connectors 指的是不同语言与 SQL 的交互接口 Management Serivices & Utillities 系统管理和工具 Connection Pool 连接池,管理缓冲用户连接,线程处理等需要缓存的需求 SQL Interface 接收用户的 SQL 指令,并且返回需要查询的结果 Parser 解析器 Optimizer 查询优化器 选取-投影-联接 Caches & Buffers 查询缓存 Engine 存储引擎 MySQL 存储引擎(loading…)memory 存储引擎CSV 存储引擎archive 存储引擎myisam 存储引擎innodb 存储引擎mysql 相关操作my.cnf 是 MySQL 的配置文件 登陆/退出 MySQL登陆 mysql -uroot -pmysql -hlocalhost -uroot -p -P3306mysql -uroot -p --prompt=命令提示符 //登陆的同时修改密令提示符mysql -uroot -p -D db_name //登陆的同时打开指定数据库 \h 主机\u 当前登陆的用户\d 当前打开的数据库\D 当前服务器的日期时间\c 取消当前命令的执行help 或者\h 或者?加上相关关键字来查看手册命令行结束符默认使用;或者\g 来结束 退出:exit | quit | \q | ctrl+c MySQL 语句SELECT USER() //得到登陆的用户SELECT VERSION() //得到MySQL的版本信息SELECT NOW() //得到当前的日期时间SELECT DATABASE() //得到当前打开的数据库 MySQL 常用函数CEIL() 进一取整FLOOR() 舍掉小数部分ROUND() 四舍五入TRUNCATE() 截取小数点后几位MOD() 取余数ABS() 取绝对值POWER() 幂运算PI() 圆周率RAND()或者 RAND(X) 0~1 之间的随机数SIGN(X) 得到数字符号EXP(X) 计算 e 的 x 次方 数据库相关操作 创建数据库CREATE {DATABASE|SCHEMA} db_name;检测数据库名称是否存在,不存在则创建CREATE DATABASE [IF NOT EXISTS] db_name;在创建数据库的同时指定编码方式CREATE DATABASE [IF NOT EXISTS] db_name [DEFAULT] CHARACTER SET [=] charset; 查看当前服务器下全部数据库SHOW DATABASES|SCHEMAS; 查看指定数据库的详细信息SHOW CREATE DATABASE db_name; 修改指定数据库的编码方式ALTER DATABASE db_name [DEFAULT] CHARACTER SET [=] charset; 打开指定数据库USE db_name; 得到当前打开的数据库SELECT DATABASE()|SCHEMA(); 删除指定的数据库DROP DATABASE db_name;如果数据库存在则删除DROP DATABASE [IF EXISTS] db_name; MySQL 数据类型 CHAR 效率高于 VARCHAR,CHAR 相当于拿空间换时间,VARCHAR 拿时间换空间CHAR 默认存储数据的时候,后面会用空格填充到指定长度;而在检索的时候会去掉后面空格;VARCHAR 在保存的时候不进行填充,尾部的空格会留下TEXT 列不能有默认值,检索的时候不存在大小写转换 数据表相关操作数据表:数据表由行(row)和列(column)来组成。每个数据表中至少有一列,行可以有零行一行或者多行组成。表名要求唯一,不要包含特殊字符,最好含义明确 创建表CREATE TABLE [IF NOT EXISTS] tbl_name(字段名称 字段类型 [完整性约束条件],字段名称 字段类型 [完整性约束条件],…)ENGINE=存储引擎 CHARSET=编码方式; 约束条件UNSIGNED 无符号,没有负数,从 0 开始ZEROFILL 零填充,当数据的显示长度不够的时候可以使用前补 0 的效果填充至指定长度,字段会自动添加 UNSIGNEDNOT NULL 非空约束,也就是插入值的时候这个字段必须要给值,值不能为空DEFAULT 默认值,如果插入记录的时候没有给字段赋值,则使用默认值PRIMARY KEY 主键,标识记录的唯一性,值不能重复,一个表只能有一个主键,自动禁止为空AUTO_INCREMENT 自动增长,只能用于数值列,而且配合索引使用,默认起始值从 1 开始,每次增长 1UNIQUE KEY 唯一性,一个表中可以有多个字段是唯一索引,同样的值不能重复,但是 NULL 值除外FOREIGN KEY 外键约束 示例 1(无约束条件) CREATE TABLE IF NOT EXISTS personal_info(id INT,username VARCHAR(20),password CHAR(32),email VARCHAR(50),age TINYINT,card CHAR(18),tel CHAR(11),salary FLOAT(8,2),married TINYINT(1),addr VARCHAR(100),sex ENUM('男','女','保密'))ENGINE=INNODB CHARSET=UTF8; 示例 2(带约束条件) CREATE TABLE IF NOT EXISTS `personal_info2`(`id` INT UNSIGNED AUTO_INCREMENT KEY COMMENT '用户编号',`username` VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名',`password` CHAR(32) NOT NULL COMMENT '密码',`email` VARCHAR(50) NOT NULL UNIQUE COMMENT '邮箱',`age` TINYINT UNSIGNED NOT NULL DEFAULT 18 COMMENT '年龄',`sex` ENUM('男','女','保密') NOT NULL DEFAULT '保密' COMMENT '性别',`tel` CHAR(11) NOT NULL UNIQUE COMMENT '电话',`addr` VARCHAR(50) NOT NULL DEFAULT '北京' COMMENT '地址',`card` CHAR(18) NOT NULL UNIQUE COMMENT '身份证号',`married` TINYINT(1) NOT NULL DEFAULT 0 COMMENT '0代表未结婚,1代表已结婚',`salary` FLOAT(8,2) NOT NULL DEFAULT 0 COMMENT '薪水')ENGINE=INNODB DEFAULT CHARSET=UTF8; 要注意单引号和反引号的使用 查看当前数据库下已有数据表SHOW TABLES;SHOW [FULL] TABLES [{FROM | IN} db_name] [LIKE 'pattern' | WHERE expr]; 查看指定数据表的详细信息SHOW CREATE TABLE tbl_name; | personal_info2 | CREATE TABLE `personal_info2` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户编号', `username` varchar(20) NOT NULL COMMENT '用户名', `password` char(32) NOT NULL COMMENT '密码', `email` varchar(50) NOT NULL COMMENT '邮箱', `age` tinyint(3) unsigned NOT NULL DEFAULT '18' COMMENT '年龄', `sex` enum('男','女','保密') NOT NULL DEFAULT '保密' COMMENT '性别', `tel` char(11) NOT NULL COMMENT '电话', `addr` varchar(50) NOT NULL DEFAULT '北京' COMMENT '地址', `card` char(18) NOT NULL COMMENT '身份证号', `married` tinyint(1) NOT NULL DEFAULT '0' COMMENT '0代表未结婚,1代表已结婚', `salary` float(8,2) NOT NULL DEFAULT '0.00' COMMENT '薪水', PRIMARY KEY (`id`), UNIQUE KEY `username` (`username`), UNIQUE KEY `email` (`email`), UNIQUE KEY `tel` (`tel`), UNIQUE KEY `card` (`card`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 | 查看表结构DESC tbl_name;DESCRIBE tbl_name;SHOW COLUMNS FROM tbl_name; +----------+------------------------+------+-----+---------+----------------+| Field | Type | Null | Key | Default | Extra |+----------+------------------------+------+-----+---------+----------------+| id | int(10) unsigned | NO | PRI | NULL | auto_increment || username | varchar(20) | NO | UNI | NULL | || password | char(32) | NO | | NULL | || email | varchar(50) | NO | UNI | NULL | || age | tinyint(3) unsigned | NO | | 18 | || sex | enum('男','女','保密') | NO | | 保密 | || tel | char(11) | NO | UNI | NULL | || addr | varchar(50) | NO | | 北京 | || card | char(18) | NO | UNI | NULL | || married | tinyint(1) | NO | | 0 | || salary | float(8,2) | NO | | 0.00 | |+----------+------------------------+------+-----+---------+----------------+ 删除指定的数据表DROP TABLE [IF EXISTS] tbl_name; 表结构相关操作add | drop | modify | change | set default | add/drop primary key | add/drop unique |rename 添加字段ALTER TABLE tbl_nameADD 字段名称 字段属性 [完整性约束条件] [FIRST|AFTER 字段名称] 删除字段ALTER TABLE tbl_nameDROP 字段名称 添加默认值ALTER TABLE tbl_nameALTER 字段名称 SET DEFAULT 默认值; 删除默认值ALTER TABLE tbl_nameALTER 字段名称 DROP DEFAULT 修改字段类型、字段属性ALTER TABLE tbl_nameMODIFY 字段名称 字段类型 [字段属性] [FIRST | AFTER 字段名称] 修改字段名称、字段类型、字段属性ALTER TABLE tbl_nameCHANGE 原字段名称 新字段名称 字段类型 字段属性 [FIRST | AFTER 字段名称] 添加主键ALTER TABLE tbl_nameADD PRIMARY KEY(字段名称) 删除主键ALTER TABLE tbl_nameDROP PRIMARY KEY; 添加唯一ALTER TABLE tbl_nameADD UNIQUE KEY|INDEX [index_name] (字段名称) 删除唯一ALTER TABLE tbl_nameDROP index_name; 修改数据表名称ALTER TABLE tbl_nameRENAME [TO|AS] new_tbl_nameRENAME TABLE tbl_name TO new_tbl_name; 修改 AUTO_INCREMENT 的值ALTER TABLE tbl_name AUTO_INCREMENT=值 数据内容相关操作增加INSERT [INTO] tbl_name[(col_name,...)] {VALUE|VALUES}(VALUES...); 不指定字段名称,需要按照建表时的字段顺序给每一个字段赋值INSERT tbl_name VALUE(value...) 列出指定字段INSERT tbl_name(字段名称,...) VALUES(值,...) INSERT … SET 的形式INSERT tbl_name SET 字段名称=值,...; INSERT … SELECTINSERT tbl_name[(字段名称...)] SELECT 字段名称,... FROM tbl_name [WHERE 条件] 一次添加多条记录INSERT tbl_name[(字段名称,...)] VALUES(VALUES,...),(VALUES,....),()... 示例 -- 测试添加记录CREATE DATABASE IF NOT EXISTS kevin DEFAULT CHARACTER SET 'UTF8';USE kevin;CREATE TABLE IF NOT EXISTS user( id INT UNSIGNED AUTO_INCREMENT KEY COMMENT '编号', username VARCHAR(20) NOT NULL UNIQUE COMMENT '用户名', age TINYINT UNSIGNED DEFAULT 18 COMMENT '年龄', email VARCHAR(50) NOT NULL DEFAULT '[email protected]' COMMENT '邮箱')ENGINE=INNODB CHARSET=UTF8;-- 不指定字段名称INSERT user VALUE(1,'kevin',24,'[email protected]');INSERT user VALUES(DEFAULT,'hex',26,'[email protected]');-- 列出指定字段的形式INSERT user(username,email) VALUES('rose','[email protected]');INSERT user(age,email,id,username) VALUES(34,'[email protected]',5,'xxxx');-- 一次插入3条记录INSERT user VALUES(NULL,'a',DEFAULT,DEFAULT),(NULL,'b',56,'[email protected]'),(NULL,'c',14,'[email protected]');-- INSERT ...SET 的形式INSERT user SET username='d',age=45,email='[email protected]';-- INSERT SELECTINSERT user(username) SELECT a FROM test; 删除DELETE FROM tbl_name [WHERE 条件]如果不添加条件,表中所有记录都会被删除DELETE 清空数据表的时候不会重置 AUTO_INCREMENT 的值,可以通过 ALTER 语句将其重置为 1 TRUNCATE [TABLE] tbl_name;清除表中所有记录会重置 AUTO_INCREMENT 的值 示例 -- 测试删除语句-- 删除用户名DELETE FROM user WHERE username='kevin';-- 删除年龄为24的用户DELETE FROM user WHERE age=24;-- 删除表中所有记录DELETE FROM user; 修改UPDATE tbl_name SET 字段名称=值,字段名称=值 [WHERE 条件]如果不添加条件,整个表中的记录都会被更新 示例 -- 测试修改语句-- 修改第一个用户的信息 id=1UPDATE user SET age=29 WHERE id=1;-- 所有用户年龄+10UPDATE user SET age=age+10;-- 将id<=5的用户年龄改为-20,将邮箱改为默认值UPDATE user SET age=age-20,email=DEFAULT WHERE id<=5; 查询(重点)SELECT select_expr,... FROM tbl_name [WHERE 条件] [GROUP BY {col_name|position} HAVING 二次筛选] [ORDER BY {col_name|position|expr} [ASC|DESC]] [LIMIT 限制结果集的显示条数] 查询表中所有记录SELECT * FROM tbl_name;指定字段的信息SELECT 字段名称,... FROM tbl_name库名.表名SELECT 字段名称,... FROM db_name.tbl_name;给字段起别名SELECT 字段名称 [AS] 别名名称,... FROM db_name.tbl_name;给数据表起别名SELECT 字段名称 ,... FROM tbl_name [AS] 别名;表名.字段名的SELECT tbl_name.col_name,... FROM tbl_name; 示例 -- 查询表中所有记录SELECT * FROM user1;-- username,addr,ageSELECT username,addr,age FROM user1;-- 查询数据库下user1表中的所有记录SELECT * FROM kevin.user1;-- 查询user1表中的id 编号 username 用户名 sex 性别SELECT id AS '编号',username AS '用户名', sex AS '性别'FROM user1;-- 给表起别名SELECT id,username FROM user1 AS u;-- 查找表名中的字段名SELECT user1.id,user1.username,user1.age FROM user1 ;SELECT u.id,u.username,u.addr,u.sex FROM user1 AS u; 避免重复关键词 DISTINCT 用于返回唯一不同的值。SELECT DISTINCT 列名称 FROM 表名称 示例 # 从titles表获取按照title进行分组,每组个数大于等于2,给出title以及对应的数目t,对于重复的emp_no进行忽略。SELECT title, COUNT(DISTINCT emp_no) AS t FROM titlesGROUP BY title HAVING t >= 2 where 条件> >= < <= != <> <=> 比较运算符IS [NOT] NULL 检测值是否为 NULL 或者 NOT NULL[NOT] BETWEEN ... AND 指定范围[NOT] IN(值,...) 指定集合[NOT] LIKE 匹配字符% % 任意长度的字符串___ 任意一个字符 示例 SELECT id,username,age FROM user1WHERE id=5;SELECT id,username,age,userDesc FROM user1WHERE userDesc<=>NULL;SELECT id,username,age,userDesc FROM user1WHERE userDesc IS NULL;SELECT id,username,age,sex FROM user1WHERE age BETWEEN 18 AND 30;-- 查询编号为1,3,5,7,9SELECT id,username,age FROM user1WHERE id IN(1,3,5,7,9,29,45,78);SELECT id,username,age,sex FROM user1WHERE sex='男' AND age>=20;SELECT id,username,age,sex,salary,addr FROM user1WHERE salary BETWEEN 60000 AND 100000 AND sex='男' AND addr='北京';SELECT id,username,age FROM user1WHERE id=1 OR username='kevin';SELECT id,username,age FROM user1WHERE username LIKE '%in%';SELECT id,username,age,sex FROM user1WHERE username LIKE '___'; group by 分组 GROUP_CONCAT()查看组中某个字段的详细信息 配合聚合函数使用COUNT() //统计记录总数。如果写的是 COUNT(字段名称),字段中的值为 NULL,不统计进来,写 COUNT(*)会统计 NULL 值SUM() //求和MAX() //求最大值MIN() //求最小值AVG() //求平均值 配合WITH ROLLUP关键使用,会在记录末尾添加一条记录,是上面所有记录的总和 HAVING子句对分组结果进行二次筛选 示例 -- 按照性别分组sexSELECT id,username,age,sex FROM user1GROUP BY sex;-- 按照addr分组SELECT username,age,sex,addr FROM user1GROUP BY addr;-- 按照性别分组,查询组中的用户名有哪些SELECT GROUP_CONCAT(username),age,sex,addr FROM user1GROUP BY sex;-- 测试COUNT()SELECT COUNT(id) FROM user1;-- 按照sex分组,得到用户名详情,并且计算组中的总人数SELECT sex,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsers FROM user1GROUP BY sex;-- 按照addr分组,得到用户名的详情,总人数,得到组中年龄的总和,年龄的最大值、最小值、平均值SELECT addr,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsers,SUM(age) AS sum_age,MAX(age) AS max_age,MIN(age) AS min_age,AVG(age) AS avg_ageFROM user1GROUP BY addr;SELECT GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsersFROM user1GROUP BY sexWITH ROLLUP;-- 按照字段的位置来分组SELECT id,sex,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsers,SUM(salary) AS sum_salary,MAX(salary) AS max_salary,MIN(salary) AS min_salary,AVG(salary) AS avg_salaryFROM user1GROUP BY 2;-- 查询age>=30的用户并且按照sex分组SELECT sex,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsersFROM user1WHERE age>=30GROUP BY sex;-- 对于分组结果进行二次筛选,条件是组中总人数>=3SELECT addr,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsersFROM user1GROUP BY addrHAVING COUNT(*)>=3;-- 要求平均薪水>=40000SELECT addr,GROUP_CONCAT(username) AS usersDetail,COUNT(*) AS totalUsers,SUM(salary) AS sum_salary,MAX(salary) AS max_salary,MIN(salary) AS min_salary,AVG(salary) AS avg_salaryFROM user1GROUP BY addrHAVING avg_salary>=40000; order by 排序ORDER BY 字段名称 ASC|DESC 示例 -- 按照id降序排列SELECT id,username,ageFROM user1ORDER BY id DESC;-- 按照age升序SELECT id,username,ageFROM user1ORDER BY age ;-- 按照多个字段排序SELECT id,username,ageFROM user1ORDER BY age ASC,id ASC;-- 测试条件+排序SELECT id,username,ageFROM user1WHERE age>=30ORDER BY age DESC;-- 实现随机记录SELECT id,username,ageFROM user1ORDER BY RAND(); LIMIT 限制结果集显示条数LIMIT 值显示结果集的前几条记录LIMIT offset,row_count从 offset 开始,显示几条记录,offset 从 0 开始 示例 -- 显示结果集的前5条记录SELECT id,username,age,sexFROM user1LIMIT 5;SELECT id,username,age,sexFROM user1LIMIT 0,5;-- 更新前3条记录,将age+5UPDATE user1 SET age=age+5 LIMIT 3;-- 按照id降序排列,更新前三条记录,将age-10UPDATE user1 SET age=age-10 ORDER BY id DESC LIMIT 3;-- 删除前三条记录DELETE FROM user1LIMIT 3;DELETE FROM user1ORDER BY id DESCLIMIT 3; 多表查询 笛卡尔积的形式 内连接的形式SELECT 字段名称,... FROM tbl_name1 INNER JOIN tbl_name2 ON 连接条件 //查询两个表中符合连接条件的记录 外连接的形式 左外连接SELECT 字段名称,... FROM tbl_name1 LEFT OUTER JOIN tbl_name2 ON 条件;左表为主表,先显示左表中的全部记录,再去右表中查询复合条件的记录,不符合的以 NULL 代替 右外连接SELECT 字段名称,... FROM tbl_name1 RIGHT [OUTER] JOIN tbl_name2 ON 条件;右表为主表,先显示右表中的全部记录,再去左表中查询复合条件的记录,不符合的以 NULL 代替 示例 -- 查询emp id username age addr dep id depName depDescSELECT e.id,e.username,e.age,e.addr,d.id,d.depName,d.depDescFROM dep AS dJOIN emp AS eON d.id=e.depId;-- 测试左外连接SELECT e.id,e.username,e.age,d.depName,d.depDescFROM emp AS eLEFT OUTER JOIN dep AS dON e.depId=d.id;-- 测试右外连接SELECT e.id,e.username,e.age,d.depName,d.depDescFROM emp AS eRIGHT JOIN dep AS dON e.depId=d.id; 外键约束(loading…)只有 InnoDB 存储引擎支持外键 建表时指定外键[CONSTRAINT 外键名称 ]FOREIGN KEY(字段名称) REFERENCES 主表(字段名称)子表的外键字段和主表的主键字段类型要相似;如果是数值型要求一致,并且无符号也要一致;如果是字符型,要求类型一致,长度可以不同如果外键字段没有创建索引,MySQL 会自动帮我们添加索引子表的外键关联的必须是父表的主键 外键约束的参照操作CASCADE 从附表删除或更新,子表也跟着删除或者更新,级联的操作SET NULL 从附表删除或者更新记录,并设置子表的外键列为 NULL。NO ACTION | RESTRICT 拒绝对父表做更新或者删除操作 动态添加外键ALTER TABLE tbl_name [CONSTRAINT 外键名称] ADD FOREIGN KEY(外键字段) REFERENCES 主表(主键字段);动态添加外键之前表中的记录一定合法的记录,没有脏值,否则外键添加不成功 动态删除外键ALTER TABLE tbl_name DROP FOREIGN KEY fk_name; 特殊形式查询(loading…)子查询SELECT 字段名称 FROM tbl_name WHERE col_name=(SELECT col_name FROM tbl_name) 联合查询 UNIONSELECT 字段名称,... FROM tbl_name1 UNION SELECT 字段名称... FROM tbl_name2; UNION ALLSELECT 字段名称,... FROM tbl_name1 UNION ALL SELECT 字段名称... FROM tbl_name2;UNION ALL 是简单的合并,UNION 会去掉表中重复记录 自身连接查询正则表达式查询^ 匹配字符串开始的部分$ 匹配字符串结束部分. 代表一个任意字符[字符集合] [abc] [a-z] [0-9][^字符集合] 除了集合中的内容s1|s2|s3 匹配 s1 或者 s2 或者 s3* 代表匹配前面的字符 0 次 1 次或者多次+ 代表匹配前面的字符至少出现 1 次字符{n} 前面的字符正好出现 n 次字符{m,n} 前面的字符至少出现 m 次,最多出现 n 次 其它注意事项SQL 语句语法规范 常用 MySQL 的关键字我们需要大写,库名、表名、字段名称等使用小写 SQL 语句支持折行操作,拆分的时候不能把完整单词拆开 数据库名称、表名称、字段名称不要使用 MySQL 的保留字,如果必须要使用,需要用反引号``将其括起来 创建的数据库名称最好有意义,名称不要包含特殊字符或者是 MySQL 关键字 常用 SQL 语句 SHOW WARNINGS; //查看上一步操作产生的警告信息 CHECK TABLE tbl_name //检测表 REPAIR TABLE tbl_name //修复表 相关链接:PHP & MySQL learning notes (4)PHP & MySQL learning notes (3)PHP & MySQL learning notes (2)PHP & MySQL learning notes (1)]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[move to windows]]></title>
<url>%2F2019%2F02%2F14%2Fmove-to-windows%2F</url>
<content type="text"><![CDATA[由于 archlinux 上出现了一些 bug,而且因为跑 SLAM,安装包占去了过多存储空间,临时决定将 blog 移植到 Windows 上来方便经常更新。 install necessary modules download nodejs and install download git and install Win+R open cmd to the right direction $ mkdir blog$ npm install hexo -g$ hexo -v //check info$ npm install //install necessary components$ hexo init //initialize folder$ hexo g //Start processing related modules $ npm install //install necessary components$ npm install hexo-deployer-git --save // deploy to git$ npm install hexo-generator-feed --save // build RSS$ npm install hexo-generator-sitemap --save // build sitemap add ssh key$ ssh-keygen -t rsa -C "your email address"$ cat /home/xxx/.ssh/id_rsa.pub //check your key load key to Github (default on Github & default you can use Github) $ ssh -T [email protected] set id & email$ git config --global user.name "your id"$ git config --global user.email "your email" copy previous files copy source files to the new catalog (as follows) _config.yml package.json node_modules scaffolds source themes type hexo s to check]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[PHP & MySQL learning notes (3)]]></title>
<url>%2F2019%2F01%2F21%2Fphp-notes2%2F</url>
<content type="text"><![CDATA[-基础笔记-慕课网 PHP 基础语法巩固(2) 课堂笔记,包含会话,文件,数据库操作等细碎的摘要 会话控制sessionHTTP 是无状态协议,HTTP 不知道请求来自哪个客户端,Session 提供在 PHP 脚本中定义全局变量的方法,使全局变量在同一个 Session 中对所有的 PHP 脚本文件内都有效,解决 HTTP 断链接的问题Session 可以减轻服务器压力,缺点在于每次请求会传输大量重复的信息Session 允许通过将数据存储在 HTTP 服务器中,使得用户在回话过程中保持该数据 session_start();$_SESSION['id'] = 'info' 每一次请求有 SessionID 区分不同的信息,SessionID 存储到 cookie 中,Session 数据通过变量$_SESSION存储到 Session 文件中 SessionID: PHP 回话启用 检查 SessionID,如果没有启动新会话 + SessionID 一直使用的 SessionID 相同,默认会话在活动,超过一定时间则视为过期 默认情况下 SessionID 存在 Cookie 中,也可以存在 URL 中 Session 函数: bool session_start() //启动新会话或重用现有会话string session_id(string $id) //获取/设置当前会话的idstring session_name(string $name) //读取/设置会话名称bool session_destroy(void) //销毁一个会话中的全部数据session.auto_start(bool) //指定会话模块在请求开始时自动启动session.name(string) //指定会话名用作cookie名字session.save_handler(string) //定义用来存储和获取与会话关联的数据处理器的名字session.save_path(string) //定义传递给存储处理器的参数session.gc_maxlifetime(int) //指定数据存在时长session.gc_probability(int) //定义在会话初始化时启动垃圾回收进程的概率 必须在 session_start()函数之前调用 session_name()函数 垃圾回收进程概率计算:gc_probability/gc_divisor cookiecookie 是服务器发送到用户浏览器上并保存在浏览器里的数据,会在浏览器下一次请求时一起发送到服务器上 session 是存储在服务器的数据cookie 是存储在客户端的数据 cookie 的用途:会话状态管理,个性化设置,浏览器行为跟踪 bool setcookie(string $name,string $value,[$expire,$path,$domain]) //名称,值,生命周期,路径,域名范围 文件操作API 文件信息相关 filetype($filename); //获取文件的类型;返回的是文件的类型,可能的值有 fifo,char,dir,block,link,file 和 unknown。如果 stat 调用失败或者文件类型未知的话 filetype() 还会产生一个 E_NOTICE 消息。filesize($filename); //获取文件的大小;返回的是字节数。如果出错返回 FALSE 并生成一条 E_WARNING 级的错误。filectime($filename); //获取文件的创建时间;返回的是时间戳。在失败时返回 FALSE。 时间以 Unix 时间戳的方式返回。filemtime($filename); //获取文件的修改时间;返回的是时间戳。在失败时返回 FALSE。fileatime($filename); //获取文件的最后访问时间;返回的是时间戳。在失败时返回 FALSE。//可以使用date()函数修改日期和时区;date_default_timezone_set('PRC');date('Y-m-d H:i:s',filectime($filename));is_readable($filename); //检测文件是否可读;返回布尔值is_writable($filename)/is_writeable($filename); //检测文件是否可写;返回布尔值is_executable($filename); //检测文件是否可执行;返回布尔值is_file($filename); //检测是否为文件;返回布尔值 文件路经相关 pathinfo($filename, $options); //获取文件路径相关信息;返回一个关联数组,包含有 path 的信息//options如果指定了,将会返回指定元素;它们包括:PATHINFO_DIRNAME,PATHINFO_BASENAME 和 PATHINFO_EXTENSION 或 PATHINFO_FILENAME。dirname($path); //返回文件中的路径部分basename($filename,$suffix); //返回路径文件名部分;file_exists($filename); //检测文件或者目录是否存在;返回布尔值 文件操作相关 touch($filename,$time,$atime); //设定文件的访问和修改时间,如果文件不存在,则会创建文件;返回布尔值//time: 使用当前系统的时间。//atime: 访问时间会被设为 atime,unlink($filename,$context); //删除文件;返回布尔值;rename($oldname,$newname,$path); //重命名或者剪切(给剪切path)一个文件或目录;返回布尔值;copy($filename); //拷贝一个文件或者目录;返回布尔值; 文件内容操作相关 $handle = fopen($filename, r|r+|w|...) //打开指定文件fread($handle, $size) //读取文件内容fwrite($handle, 'info',$size)|fput() //写入内容,之前有内容会覆盖ftell($handle) //读取指针位置fseek($handle,$size) //移动指针的位置fpassthru() //输出文件指针处的所有剩余数据rewind($handle) //重置文件指针ftruncate($handle,$size) //将文件截断到指定长度fgetc($handle) //读取一个字符fgets($handle) //读取一行字符fgetss($handle) //读取一行并过滤掉 HTML 标记fgetcsv() //从文件指针中读入一行并解析 CSV 字段fputcsv() //将行格式化为 CSV 并写入文件指针file_get_contents() //将整个文件读入一个字符串file_put_contents() //将一个字符串写入文件,和依次调用 fopen(),fwrite() 以及 fclose() 功能一样。file() //把整个文件读入一个数组中readfile() //读取文件并写入到输出缓冲feof($handle) //测试文件指针是否到了文件结束的位置fclose() //关闭文件parse_ini_file($filename) //解析一个配置文件parse_ini_string($ini) //解析配置字符串highlight_string($str) //字符串的语法高亮highlight_file() //语法高亮一个文件 ‘r’:只读方式打开,将文件指针指向文件头。‘r+’:读写方式打开,将文件指针指向文件头。‘w’:写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。‘w+’:读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。‘a’:写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。‘a+’:读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。‘x’:创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。‘x+’:创建并以读写方式打开,其他的行为和 ‘x’ 一样。 函数和类的封装 创建文件 可以用 touch()创建,也可以直接 file_get_contents() function create_file(string $filename){ //检测文件是否存在,不存在则创建 if(file_exists($filename)){ return false; } //检测目录是否存在,不存在则创建 if(!file_exists(dirname($filename))){ //创建目录,可以创建多级 mkdir(dirname($filename),0777,true); } // if(touch($filename)){ // return true; // } // return false; if(file_put_contents($filename,'')!==false){ return true; } return false;} 删除文件 function del_file(string $filename){ //检测删除的文件是否存在,并且是否有权限操作 if(!file_exists($filename)||!is_writable($filename)){ return false; } if(unlink($filename)){ return true; } return false;} 拷贝文件 function copy_file(string $filename,string $dest){ //检测$dest是否是目标并且这个目录是否存在,不存在则创建 if(!is_dir($dest)){ mkdir($dest,0777,true); //0777为权限 } $destName=$dest.DIRECTORY_SEPARATOR.basename($filename); //检测目标路径下是否存在同名文件 if(file_exists($destName)){ return false; } //拷贝文件 if(copy($filename,$destName)){ return true; } return false;} 重命名文件 function rename_file(string $oldName,string $newName){ //检测原文件并且存在 if(!is_file($oldName)){ return false; } //得到原文件所在的路径 $path=dirname($oldName); $destName=$path.DIRECTORY_SEPARATOR.$newName; //路径下有文件名,重命名失败 if(is_file($destName)){ return false; } if(rename($oldName,$newName)){ return true; } return false;} 剪切文件 function cut_file(string $filename,string $dest){ //检查文件和路径是否都存在 if(!is_file($filename)){ return false; } if(!is_dir($dest)){ mkdir($dest,0777,true); } $destName=$dest.DIRECTORY_SEPARATOR.basename($filename); if(is_file($destName)){ return false; } if(rename($filename,$destName)){ return true; } return false;} 返回文件信息 function get_file_info(string $filename){ //检查文件存在且可读 if(!is_file($filename)||!is_readable($filename)){ return false; } return [ 'atime'=>date("Y-m-d H:i:s",fileatime($filename)), 'mtime'=>date("Y-m-d H:i:s",filemtime($filename)), 'ctime'=>date("Y-m-d H:i:s",filectime($filename)), 'size'=>trans_byte(filesize($filename)), 'type'=>filetype($filename) ];} 字节转换 function trans_byte(int $byte,int $precision=2){ $kb=1024; $mb=1024*$kb; $gb=1024*$mb; $tb=1024*$gb; if($byte<$kb){ return $byte.'B'; }elseif($byte<$mb){ return round($byte/$kb,$precision).'KB'; }elseif($byte<$gb){ return round($byte/$mb,$precision).'MB'; }elseif($byte<$tb){ return round($byte/$gb,$precision).'GB'; }else{ return round($byte/$tb,$precision).'TB'; }} 读取文件内容返回字符串 function read_file(string $filename){ //检测是否是一个文件并且文件可读 if(is_file($filename) && is_readable($filename)){ return file_get_contents($filename); } return false;} 读取文件内容返回数组 function read_file_array(string $filename,bool $skip_empty_lines=false){ //检测是否是一个文件并且文件可读 if(is_file($filename)&&is_readable($filename)){ if($skip_empty_lines){ //如果有空行就过滤掉 return file($filename,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES); }else{ return file($filename); } } return false;} 文件中写入内容 写入的内容是数组或者对象需要做序列化处理 function write_file(string $filename,$data){ $dirname=dirname($filename); //检测目标路径是否存在 if(!file_exists($dirname)){ mkdir($dirname,0777,true); } //判断内容是否是数组或者对象 if(is_array($data)||is_object($data)){ //序列化数据 $data=serialize($data); } //向文件中写入内容 if(file_put_contents($filename,$data)!==false){ return true; }else{ return false; }} 非空文件中写入内容 function write_file1(string $filename,$data,bool $clearFlag=false){ $dirname=dirname($filename); //检测目标路径是否存在 if(!file_exists($dirname)){ mkdir($dirname,0777,true); } //检测文件是否存在并且可读 if(is_file($filename)&&is_readable($filename)){ //读取文件内容,之后和新写入的内容拼装到一起 if(filesize($filename)>0){ $srcData=file_get_contents($filename); } } //判断内容是否是数组或者对象 if(is_array($data)||is_object($data)){ //序列化数据 $data=serialize($data); } //拼装到一起 $data=$srcData.$data; //向文件中写入内容 if(file_put_contents($filename,$data)!==false){ return true; }else{ return false; }} 截断文件到指定大小 function truncate_file(string $filename,int $length){ //检测是否是文件且可写 if(is_file($filename)&&is_writable($filename)){ $handle=fopen($filename,'r+'); $length=$length<0?0:$length; ftruncate($handle,$length); fclose($handle); return true; } return false;} 下载文件 在 html 里添加下载链接 建立down_file()函数 建立 php 文件进行下载 <a href="download.php?filename=download.zip">file_name.zip</a> //$allowDownExt 允许下载的文件类型function down_file(string $filename,array $allowDownExt=array('jpeg','jpg','png','gif','txt','html','php','rar','zip')){ //检测下载文件是否存在,并且可读 if(!is_file($filename)||!is_readable($filename)){ return false; } //检测文件类型是否允许下载 $ext=strtolower(pathinfo($filename,PATHINFO_EXTENSION)); if(!in_array($ext,$allowDownExt)){ return false; } //通过header()发送头信息 //告诉浏览器输出的是字节流 header('Content-Type:application/octet-stream'); //告诉浏览器返回的文件大小是按照字节进行计算的 header('Accept-Ranges: bytes'); //告诉浏览器返回的文件大小 header('Accept-Length: '.filesize($filename)); //告诉浏览器文件作为附件处理,告诉浏览器最终下载完的文件名称 header('Content-Disposition: attachment;filename=king_'.basename($filename)); //读取文件中的内容 //readfile($filename); //exit; //规定每次读取文件的字节数为1024字节,直接输出数据 $read_buffer=1024; $sum_buffer=0; $handle=fopen($filename,'rb'); while(!feof($handle) && $sum_buffer<$filesize){ echo fread($handle,$read_buffer); $sum_buffer+=$read_buffer; } fclose($handle); exit;} $filename=$_GET['filename'];down_file($filename); 单文件上传 function upload_file(array $fileInfo,string $uploadPath='./uploads',bool $imageFlag=true,array $allowExt=array('jpeg','jpg','png','gif'),int $maxSize=2097152){ define('UPLOAD_ERRS',[ 'upload_max_filesize'=>'超过了PHP配置文件中upload_max_filesize选项的值', 'form_max_size'=>'超过了表单MAX_FILE_SIZE选项的值', 'upload_file_partial'=>'文件部分被上传', 'no_upload_file_select'=>'没有选择上传文件', 'upload_system_error'=>'系统错误', 'no_allow_ext'=>'非法文件类型', 'exceed_max_size'=>'超出允许上传的最大值', 'not_true_image'=>'文件不是真实图片', 'not_http_post'=>'文件不是通过HTTP POST方式上传上来的', 'move_error'=>'文件移动失败' ]); //检测是否上传是否有错误 if($fileInfo['error']===UPLOAD_ERR_OK){ //检测上传文件类型 $ext=strtolower(pathinfo($fileInfo['name'],PATHINFO_EXTENSION)); if(!in_array($ext,$allowExt)){ echo UPLOAD_ERRS['no_allow_ext']; return false; } //检测上传文件大小是否符合规范 if($fileInfo['size']>$maxSize){ echo UPLOAD_ERRS['exceed_max_size']; return false; } //检测是否是真实图片 if($imageFlag){ if(@!getimagesize($fileInfo['tmp_name'])){ echo UPLOAD_ERRS['not_true_image']; return false; } } //检测文件是否通过HTTP POST方式上传上来的 if(!is_uploaded_file($fileInfo['tmp_name'])){ return UPLOAD_ERRS['not_http_post']; } //检测目标目录是否存在,不存在则创建 if(!is_dir($uploadPath)){ mkdir($uploadPath,0777,true); } //生成唯一文件名,防止重名产生覆盖 $uniName=md5(uniqid(microtime(true),true)).'.'.$ext; $dest=$uploadPath.DIRECTORY_SEPARATOR.$uniName; //移动文件 if(@!move_uploaded_file($fileInfo['tmp_name'],$dest)){ echo UPLOAD_ERRS['move_error']; return false; } echo '文件上传成功'; return $dest; }else{ switch($fileInfo['error']){ case 1: // $mes='超过了PHP配置文件中upload_max_filesize选项的值'; $mes=UPLOAD_ERRS['upload_max_filesize']; break; case 2: $mes=UPLOAD_ERRS['form_max_size']; break; case 3: $mes=UPLAOD_ERRS['upload_file_partial']; break; case 4: $mes=UPLOAD_ERRS['no_upload_file_select']; break; case 6: case 7: case 8: $mes=UPLAOD_ERRS['upload_system_error']; break; } echo $mes; return false; }} 压缩单个文件 ZipArchive()一个用 Zip 压缩的文件存档类 压缩包要打开后将文件添加到压缩包中 function zip_file(string $filename){ if(!is_file($filename)){ return false; } $zip=new ZipArchive(); $zipName=basename($filename).'.zip'; //打开指定压缩包,不存在则创建,存在则覆盖 if($zip->open($zipName,ZipArchive::CREATE|ZipArchive::OVERWRITE)){ //将文件添加到压缩包中并删除文件 if($zip->addFile($filename)){ @unlink($filename); } $zip->close(); return true; }else{ return false; }} 多文件压缩 function zip_files(string $zipName,...$files){ //检测压缩包名称是否正确 $zipExt=strtolower(pathinfo($zipName,PATHINFO_EXTENSION)); if('zip'!==$zipExt){ return false; } $zip=new ZipArchive(); if($zip->open($zipName,ZipArchive::CREATE|ZipArchive::OVERWRITE)){ foreach($files as $file){ if(is_file($file)){ $zip->addFile($file); } } $zip->close(); return true; }else{ return false; }} 解压缩 function unzip_file(string $zipName,string $dest){ //检测要解压压缩包是否存在 if(!is_file($zipName)){ return false; } //检测目标路径是否存在 if(!is_dir($dest)){ mkdir($dest,0777,true); } $zip=new ZipArchive(); if($zip->open($zipName)){ $zip->extractTo($dest); $zip->close(); return true; }else{ return false; }} 函数和类的封装源码: code/lib/file.func.php MySQL具体参考 PHP & MySQL learning notes (1)->3.mySQL PHP 操作 MySQL MySQL:非永久链接,性能低,PHP5.5 之后废弃 MySQLi:永久链接,减轻了服务器压力 PDO:实现 MySQLi 常用功能,支持大部分数据库 连接数据库:mysql -uroot -p password选择数据库:use db设置字符集:set names utf8 mysql_select_db("DATABASE NAME", $con)mysql_connect($server,$username,$password) //链接数据库mysql_select_db($database_name) //选择数据库名mysql_set_charset($charset) //设置字符集mysql_query($query) //执行INSERT,UPDATE,DELETE,DROP之类的操作,返回boolmysql_query($query) //执行SELECT操作,成功返回resource,失败返回FALSE 代码示例 header('content-type:text/html;charset=utf-8');//1、连接数据库$link = @mysql_connect('localhost','root','') or die('数据库连接失败!');//2、选择数据库mysql_select_db('test') or die('选择的数据库不存在!');//3、设置字符集mysql_set_charset('utf8');//添加数据$result = mysql_query("INSERT INTO users VALUES(NULL ,'李四',20)");//var_dump($result);//修改数据$result = mysql_query("UPDATE users SET money=25 where id=3");//var_dump($result);//删除单条数据$result = mysql_query("DELETE FROM users where id=3");//var_dump($result);//删除数据表$result = mysql_query("DROP TABLE test");//var_dump($result);//查询$result = mysql_query("SELECT * FROM users");//$line = mysql_fetch_row($result);//$line = mysql_fetch_assoc($result);while($line = mysql_fetch_array($result,MYSQL_ASSOC)){ $data[] = $line;}var_dump($data);//array (size=3)// 'id' => string '1' (length=1)// 'name' => string '慕课' (length=6)// 'money' => string '100' (length=3)//关闭数据库连接mysql_close($link); MySQLi 操作$connect = mysqli_connect('host','username','password'.'database'); //面向过程方式链接数据库$result = mysqli_query($connect,$sql); //执行SQL语句mysqli_fetch_all($result) //获取结果集 错误及常用命令 Parse error(解析错误): syntax error(语法错误), unexpected ‘<’, expecting end of file Notice(通知): Undefined variable(未定义的变量): sdkljflskdjflksdjflksdjfklj Catchable fatal(致命) error: Object of class stdClass could not be converted to string Warning(警告): settype(): Invalid(非法) type</br> header('content-type:text/html;charset=utf-8');date_defalut_timezone_set('PRC');@ //PHP提供的错误信息屏蔽的专用符号echo($var,....) //输出一个或者多个字符串var_dump($var) //打印变量的详细信息,可以一次打印一个或者多个变量的详细信息print_r($var) //打印数组的信息unset($var,...) //销毁变量,可以一次销毁一个或者多个,销毁之后变量的值为nulltime() //返回当前的 Unix 时间戳is_[int|float|double|bool...]($var) //判断变量的类型isset() //检测变量是否存在function_exists() //判断函数谁否存在file_exists() //判断文件是否存在$var = file_get_contents($filename) //得到文件中的内容,返回的是字符串serialize() //产生一个可存储的值的表示unserialize() //从已存储的表示中创建 PHP 的值setcookie(string $name, string $value, int $expire = 0, string $path = "", string $domain = "") //设置coockie:$name名称 $value值 $expire生命周期 $path可用路径 $domain可用域名范围$var = strip_tags() //从字符串中去除 HTML 和 PHP 标记exit()|die(); //输出一个消息并且退出当前脚本 相关链接:mysql 笔记PHP & MySQL learning notes (2)PHP & MySQL learning notes (1)]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>php</tag>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Machine Learning API Collection]]></title>
<url>%2F2019%2F01%2F15%2Fml-api%2F</url>
<content type="text"><![CDATA[无聊收集的一个机器学习的 api 仓库,不定期更新 人脸与图片识别 api Animetrics Face Recognition: 该 API 能够用于图片中的人脸检测,并且将其与已知的部分人脸进行匹配分析;该 API 还支持从某个待搜索的集合中添加或者移除某个分类,或者从某个分类中添加或者删除某张人脸图片。 Betaface: 同样是提供人脸识别与检测的在线服务。它支持多人脸检测、人脸裁剪、123 个人脸特征点提取、人脸验证、识别以及大型数据库中的相似性搜索提取。 Eyedea Recognition: 致力于提供高阶的计算机视觉解决方案,主要包括对象检测与识别。其识别服务提供了常见的眼部、人脸、车辆、版权以及果盘识别,该 API 主要的价值在于对于对象、用户以及行为的快速识别。 Face++: 为应用提供面部的检测、识别以及分析服务,用户可以通过 API 调用训练模型,进行人脸检测、人脸识别、人脸分类、图像修正、创建人脸分组等等服务。 FaceMark: 提供了能够在正面照片中检测 68 个特征点以及侧面照片中检测 35 个特征点的服务。 FaceRect: 提供了非常强力与完整的面部检测的 API ,包括在正面照片与侧面照片中检测面部以及在单张照片中提取多个面部的功能;它还能将结果以 JSON 格式输出,包括检测到的眼睛、鼻子、嘴等等面部特征。 Google Cloud Vision API: 架构于著名的 TensorFlow 之上,能够高效地学习与预测图片中的内容。它能够有助于用户搜索最爱的图片,并且获取图片中丰富的注释。它还能将图片按照船、狮子、埃菲尔铁塔等等不同的类别进行分类,并且对照片中不同表情的面部进行识别,除此之外它还能将图片中不同国家的语言打印出来。 IBM Watson Visual Recognition: 该 API 能够辅助理解图片内容,包括图片标记、人脸识别、年龄估计以及性别判断,还能根据人脸相似度进行搜索。开发者能够在该服务的基础上结合自身业务特点定制出各式各样奇妙的产品。 Kairos: 该平台方便开发者快速添加 情感分析 与 人脸识别 的功能到应用与服务中。 Microsoft Cognitive Service – Computer Vision: 该 API 能够根据用户输入与用户选择分析可视化内容。譬如根据内容来标记图片、进行图片分类、人类识别并且返回他们的相似性、进行领域相关的内容识别、创建图片的内容描述、定位图片中的文本、对图片内容进行成人分级等。 Rekognition: 该 API 能够根据社交图片应用的特点提供快速面部识别与场景识别。譬如基于人眼、嘴、面部以及鼻子等等特征进行性别、年龄以及情绪预测。 Skybiometry Face Detection and Recognition: 该 API 提供人脸检测与识别服务,新版本的 API 还提供了深色微分功能. 文本分析,自然语言处理,情感分析 api Bitext 提供了目前市场上来说几乎最准确的基于情感的多主题识别,目前包括四个语义服务:实体与概念抽取、情感分析与文本分类;该 API 总共支持 8 种不同的语言。 Diffbot Analyze: 为开发者提供了从任何网页中识别、分析以及提取主要内容与区块的功能。 Free Natural Language Processing Service: 提供了包括情感分析、内容提取以及语言检测等功能。它同样是 mashape.com 这个大型云 API 市场中的畅销产品之一。 Google Cloud Natural Language API: 该 API 提供了对于文档的架构与含义进行分析的功能,包括情感分析、实体识别以及文本标注等。 IBM Watson Alchemy Language: 该 API 能够辅助电脑学习如何阅读以及进行一些文本分析任务。譬如将非结构化数据按照领域模型转化为结构化数据,使其能够服务于社交媒体监测、商业智能、内容推荐、商业交易以及定向广告等等服务。 MeaningCloud Text Classification: 该 API 提供了部分预分类的功能:文本提取、分词、停用词设置以及同义词提取等等。 Microsoft Azure Text Analytics API 基于 Azure Machine Learning 实现的一系列文本分析服务。该 API 能够用于情感分析、关键语句提取、语言检测以及主题识别这些非结构化文本的处理任务。该 API 并不需要使用者提供相关的训练数据,能够大大降低使用门槛。 Microsoft Cognitive Service – Text Analytics: 提供了情感检测、关键语句提取、主题以及语言分析等功能。该分组中其他的 API 还包括 Bing 拼写检测、语言理解、文本分析、Web 语言模型等等。 nlpTools: 简单的采用 JSON 传输格式的提供了自然语言处理功能的 HTTP RESTful 服务。它能够提供对于在线媒体的情感分析与文本分类等服务。 Semantic Biomedical Tagger: 能够利用文本分析技术提取出文档中的 133 个生物医药学相关的实体词汇并且将它们链接到知识库中。 Thomson Reuters Open Calais™: Calais 基于自然语言处理与机器学习技术,能够分类与关联文档中的实体信息(人名、地名、组织名等)、事实信息(员工 x 为公司 y 工作)、事件信息(员工 z 在 x 日被任命为 y 公司的主席) 。 Yactraq Speech2Topics 提供了基于语音识别与自然语言处理技术的将语音内容转化为主题数据的云服务。 语言翻译 api Google Cloud Translation: 能够在数以千计的语言之间完成文本翻译工作。该 API 允许网页或者程序方便地接入这些翻译服务。 IBM Watson Language Translator: 能够在不同语言之间进行文本翻译,该服务允许开发者基于独特的领域术语与语言特性进行自定义模型开发。 LangId: 能够快速地从多语言中检索结果的服务,并不需要使用者指定哪种语言,并且能够返回结果对应的语言类型。 Microsoft Cognitive Service – Translator: 能够自动地在翻译之前进行语言类型检测,支持 9 种语言的语音翻译以及 60 种语言的文本翻译。 MotaWord: 快速地人工翻译平台,提供了超过 70 种语言支持。该 API 同样允许开发者查询翻译报价、上传带有文档说明与样式指南的翻译项目请求、自动追踪翻译进度以及进行实时反馈等。 WritePath Translation: API 允许开发者将 WritePath 功能集成到自定义应用中,包括字数检索、提交文本翻译任务、以及获取翻译信息等等。 预测与其他机器学习 api Amazon Machine Learning: 寻找数据中的隐藏模式信息,典型的用法包括诈骗检测、天气预报、市场营销以及点击预测等。 BigML: 提供基于云的机器学习与数据分析服务,允许用户以 HTTP 请求的方式自己创建数据源以及选择合适的模型来处理有监督或者无监督的机器学习任务。 Ersatz: 基于 GPU 支持的深度神经网络提供的预测服务,允许用户以 API 方式进行交互。Ersatz 中还利用增强学习来合并不同的神经网络模型来提升整体的效果。 Google Cloud Prediction: 提供了用于构建机器学习模型的 RESTful API 。这些工具能够通过分析数据来提取出应用中数据的不同特征,譬如用户情感、垃圾信息检测、推荐系统等等。 Google Cloud Speech API: 能够提供超过 80 种语言的快速与准确的语音识别以及转化服务。 Guesswork.co: 能够为电商网站提供产品推荐引擎,Guesswork 可以通过基于 Google 预测 API 构建的语义化引擎来对用户行为进行预测。 Hu:toma: 帮助世界各地的开发者构建商用级别的深度学习聊天机器人。 IBM Watson Conversation : 帮助构建可以部署在多个消息平台或者网页上的,能够理解自然语言的聊天机器人。其他类似的 API 还包括 Dialog、Natural Language Classifier、Personality Insights、Document Conversion 以及 Tone Analyzer. IBM Watson Speech : 包含了 语音到文本 以及 文本到语音 之间的转化功能(譬如创建语音控制的应用)。 IBM Watson Data Insights: 该系列的服务包含了三个 API :AlchemyData News、Discovery 以及 Tradeoff Analytics。AlchemyData 提供了对于大量的新闻、博客内容的高级别定向搜索与趋势分析的服务。Tradeoff Analytics 则是帮助用户在多目标优化时进行有效抉择。 IBM Watson Retrieve and Rank: 开发者可以将自定义数据导入到服务中,并且使用相关的关联发算法来训练机器学习模型。服务的输出包括了一系列相关的文档与元数据,譬如某个联络中心的代理能够基于该服务提高呼叫的平均处理时间。 Imagga: 能够为你的图片自动打标签,从而允许你的图片可以被关联搜索到。 indico: 提供了文本分析(情感分析、Twitter 参与度、表情分析等)以及 图片分析(面部表情识别、面部定位)。indico 的 API 可以免费试用并且不需要任何的训练数据。 Microsoft Azure Cognitive Service API : 基于预测分析提供机器学习推荐服务,譬如个性化产品推荐等,可以用来代替传统的 Azure Machine Learning Recommendations 服务。新版本提供了批处理支持,更好地 API 检索服务、更清晰的 API 使用界面以及更好的注册与账单界面等。 Microsoft Azure Anomaly Detection API : 能够在序列数据中检测出异常数据,譬如检测内存使用过程中是否存在内存泄露的情况。 Microsoft Cognitive Service – QnA Maker: 将信息提取为会话式的、易于浏览的数据形式。其他类似的 API 还包括 Academic Knowledge、Entity Linking、Knowledge Exploration 以及 Recommendations。 Microsoft Cognitive Service – Speaker Recognition: 帮助应用来分析检测出当前的发言者。其他的类似于的 API 还包括 Bing Speech (将语音转化为文本并且理解其大致含义)、 Custom Recognition 等等。 NuPIC : 由 NuPIC 社区运行与维护的开源项目,其基于 Python/C++ 实现了 Numenta’s Cortical Learning 算法并对外提供 API 服务。该 API 允许开发者能够使用基本算法或者分层算法,也可以选择使用其他的平台功能。 PredicSis: 能够通过预测分析与大数据技术提供市场营销的效用与收益。 PredictionIO: 基于 Apache Spark、HBase 以及 Spray 这些著名的开源项目搭建的开源机器学习服务。典型的 API 包括了创建与管理用户信息及其行为记录、检索项目与内容、基于用户进行个性推荐等等。 RxNLP – Cluster Sentences and Short Texts: 提供了文本挖掘与自然语言处理的服务。其中语句聚类 API 能够将不同的语句进行分类,譬如将不同新闻文章中的语句或者 Twitter、Facebook 上提取出来的短文本划分到不同的分组中。 Sightcorp F.A.C.E.: 该 API 能够帮助第三方应用来更好地理解用户行为,并且根据年龄、性别、面部表情、头部姿势以及种族划分来进行相似面部的分析与搜索。]]></content>
<categories>
<category>repo</category>
</categories>
<tags>
<tag>machine_learning</tag>
</tags>
</entry>
<entry>
<title><![CDATA[基于RGB-D相机数据的三维场景构建]]></title>
<url>%2F2019%2F01%2F10%2Fslam-rgbd%2F</url>
<content type="text"><![CDATA[-研究笔记-  简要介绍通过 RGB-D 相机采集到的一个场景的图像数据和深度数据,对这个场景进行三维点云地图的简单构建。整个步骤分为特征提取,特征匹配,位姿估计,三维重建。首先从图像中提取 ORB 特征,采用暴力匹配的方法得到图像间特征点的匹配结果,然后采用 PnP 估计相机的位姿筛选出关键帧,最后利用当前帧简历三维场景地图。后端使用 Eigen 加速矩阵计算,g2o 对相机位姿进行优化,使用 PCL 拼接点云。实验数据采用 TUM 的 RGB-D 数据集。 RGB-D 相机模型RGB-D 相机能够主动测量每个像素的深度,比双目相机通过视差计算更为主动。相比较单目相机,RGB-D 相机没有复杂的深度恢复过程,使得算法更为简单;相较其它于双目相机,RGB-D 相机有着更好的经济性,节省了不少成本。但是 RGB-D 相机的深度测量范围有限,只能用于室内,从一定程度上限制了其适用性。RGB-D 相机向探测目标发射一束光线,根据返回的结构光图案,计算物体与自身之间的距离。在测量完深度后,自己完成深度与彩色图像像素之间的配对,输出一一对应的彩色图和深度图。之后通过得到的距离和色彩信息,计算像素的三维相机坐标,进行点云构建。 ORB 特征提取和匹配直接从图像本身考虑运动估计会比较复杂,也会消耗大量计算资源,所以一般采用选取图像中比较有代表性的点,在这些点的基础上讨论相机的位姿变化并进行定位。特征点由关键点和描述子两部分组成。视觉领域常用的特征检测算法有 SIFT、SURF、ORB 等。SIFT 和 SURF 算法提取效率和匹配效率都不高,本实验选择实时性更好的 ORB (Oriented FAST and Rotated BRIEF) 特征。 ORB 算法是 Ethan Rublee 在 2011 年提出的,是一种新的特征检测和描述算法。它改进了 FAST 检测子,并采用速度极快的 BRIEF 描述子,使图像提取环节得到加速。 FAST 主要检测局部像素灰度变化过于明显的地方,如果一个像素和邻域的像素差别比较大,那么他更可能是角点。ORB 中对原始的 FAST 进行改进,ORB 指定了要提取的角点数量 N,对原始的 FAST 角点分别计算 Harris 响应值,然后取 Top-N 个具有最大响应值得角点作为最终的角点集合。 另外 ORB 使 FAST 角点具有尺度和旋转的描述。通过对图像进行不同层次的降采样,获得不同分辨率的图像,并在每一层次进行角点检测得到尺度不变性;特征旋转通过灰度质心法 (Intensity Centroid) 实现: 定义图像块的矩为 通过矩可以找到图像块的质心 连接图像块的几何中心 O 与质心 C,得到从 O 到 C 的方向向量,则特征点的方向可以定义为 通过以上方法,FAST 具备尺度和旋转描述 本实验采用暴力匹配 (Brute-Force Matcher) 的方法,计算每一个特征点与所有描述子的距离,然后排序。由于描述子距离表示了两个特征之间的相似程度,所以取最近的作为特征点。对于二进制描述子 BRIEF 采用汉明距离 (Hamming distance) 作为度量。 PnP 位姿估计PnP (Perspective-n-Point) 是求解三维到二维点对运动的方法,不需要使用对极约束(存在初始化,纯旋转和尺度问题,且一般需要 8 对点),可以在较少的匹配点(最少 3 对点)中获得较好的运动估计。特征点的三维位置可以直接由 RGB-D 相机的深度图确定。 常用的 PnP 问题求解有 3 对点估计位姿 P3P、直接线性变换 (DLT) 、EPnP (Efficient PnP) 、UPnP 以及非线性优化建立最小二乘求解 (Bundle Adjustment)。本实验采用 OpenCV 提供的 EPnP 筛选匹配点来求解相机位姿。将数据集中相邻两帧图像之间进行比较,确认相机的旋转参数和平移参数。 场景地图重建根据估算的相机位姿记录下的相机旋转平移参数,即相机的内参数和外参数,将 RGB-D 数据转化为点云 (Point Cloud),然后通过 PCL (Point Cloud Library) 进行拼接,最后得到由离散点组成的点云地图。把生成的点云地图以 PCD 格式存储,可通过 PCL 可视化程序打开相应文件。 后端优化Eigen:C++开源线性代数库,提供有关矩阵的线性代数运算。g2o:C++开源框架,利用图优化框架对 PnP 和位姿图进行优化,使用 Eigen 进行矩阵计算。PCL:C++开源编程库,实现了大量点云相关的通用算法和高效数据结构,涉及到点云获取、滤波、分割、配准、检索、特征提取、识别、追踪、曲面重建、可视化等。 实验结果通过 FAST 计算出的所有特征结点并通过 BRIEF 描述子进行配对暴力匹配计算特征点和描述子的距离,进行优化后筛选有效的特征点通过 PnP 算法估计相机的匹配点并计算出相机的旋转参数 R 和位移参数 t将 Tum 数据集中的图片信息和深度信息进行两两帧特征提取和匹配,得到一组特征点和相机的位姿变换矩阵,利用 PCL 进行点云地图构建 总结关键点的提取和描述子的计算非常耗时,尽管 ORB 已经做到了一定的优化,但进行特征提取仍然会占去实时三维建图的大部分时间。一幅图可以有几十万个像素,只提取特征点会丢弃大部分有用的图像信息,另外面对没有明显纹理的场景,室外亮环境,现有的 RGB-D 和 PnP 方案明显还有待完善的地方。两辆帧的比较只能满足局部地图的匹配和优化,面对一个完整的场景还需要对全局进行更加真实和实时的建模。点云建图也需要利用如深度滤波等滤波算法对结果进行优化,最终达到对相机拍摄到的场景进行半稠密地图和稠密地图重建的效果。]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>slam</tag>
</tags>
</entry>
<entry>
<title><![CDATA[使用 layoutit 设计简易留言板功能]]></title>
<url>%2F2018%2F11%2F18%2Flayoutit%2F</url>
<content type="text"><![CDATA[-基础练习-Layoutit是基于 bootstrap2.0 的一个可视化布局模板, 可以点击模板里的文字进行修改, 也可以通过点击弹出的编辑框进行富文本修改. 拖动区块能实现排序。尝试用 Layoutit 进行快速可视化布局,练习 PHP 的_POST 和_GET,后台数据用文件存储,未使用数据库 后台步骤 创建msg.md,将文件中的内容创建成 PHP 的值,读取到$msgs:$msgs=unserialize($string); header('content-type:text/html;charset=utf-8');date_default_timezone_set('PRC');$filename="msg.md";$msgs=[];//检测文件是否存在if(file_exists($filename)){ //读取文件中的内容 $string=file_get_contents($filename); if(strlen($string)>0){ $msgs=unserialize($string); }} 检测到用户提交留言 读取$username, $title, $content, $time 组成关联数组: $data=compact('username','title','content','time'); 写入新的数据到$msgs: array_push($msgs,$data); 产生一个存储的值: $msgs=serialize($msgs); 报告留言成功或失败 if(isset($_POST['pubMsg'])){ $username=$_POST['username']; $title=strip_tags($_POST['title']); $content=strip_tags($_POST['content']); $time=time(); //将其组成关联数组 $data=compact('username','title','content','time'); array_push($msgs,$data); $msgs=serialize($msgs); if(file_put_contents($filename,$msgs)){ echo "<script>alert('留言成功!');location.href='22-msg.php';</script>"; }else{ echo "<script>alert('留言失败!');location.href='22-msg.php';</script>"; }} 将$msgs 中的内容显示在留言板上 检测到$msgs 存在且数组有内容 将$msgs中的所有数组键名按顺序读取,分别在网页中输出:foreach($msgs as $val) <?php if(is_array($msgs)&&count($msgs)>0):?>...<?php $i=1;foreach($msgs as $val):?> <tr class="success"> <td> <?php echo $i++;?> </td> <td> <?php echo $val['username'];?> </td> <td> <?php echo $val['title'];?> </td> <td> <?php echo date("m/d/Y H:i:s",$val['time']);?> </td> <td> <?php echo $val['content'];?> </td> </tr><?php endforeach;?><?php endif;?> 表格输出 编号 用户 标题 时间 内容 1 KevinW test 11/18/2018 15:59:25 测试留言 Layoutit 页面设计 </head> Kevin_W的留言板-V1.1.0 Hello, Layoutit! 这是一个可视化布局模板, 你可以点击模板里的文字进行修改, 也可以通过点击弹出的编辑框进行富文本修改. 拖动区块能实现排序. 参看更多 » 请留言 用户 标题 内容 L2Dwidget.init({"pluginRootPath":"live2dw/","pluginJsPath":"lib/","pluginModelPath":"assets/","tagMode":false,"debug":false,"model":{"jsonPath":"/live2dw/assets/haruto.model.json"},"display":{"position":"left","width":100,"height":200},"mobile":{"show":true},"log":false}); msg.phpmsg.md]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>bootstrap2.0</tag>
<tag>php</tag>
</tags>
</entry>
<entry>
<title><![CDATA[PHP & MySQL learning notes (2)]]></title>
<url>%2F2018%2F11%2F05%2Fphp-notes%2F</url>
<content type="text"><![CDATA[-基础笔记-慕课网 PHP 基础语法巩固(2) 课堂笔记,包含基本语法,变量和数据和函数等细碎的摘要 PHP 使用环境和 IDE LAMP(build): Linux+Apache+MySQL+PHP LNMP: Linux+Nginx+MySQL+PHP LNMPA: Linux+Nginx+MySQL+PHP+Apache WAMP(build): Window+Apache+MySQL+PHP 集成环境: xampp, wampserver, phpstudy IDE: vscode,Atom, Sublime Text3, PHPStorm, ZendStudio 基础语法 标准风格:<?php 代码段; ?>如果文档中只有 PHP 代码,结束标记要省略掉如果文档中不只有 PHP 代码,一定要保证 PHP 的开始和结束标记成对出现,可以出现任意位置,任意多次都可以 短风格:<? 代码段; ?>需要配置 PHP 配置文件 php.ini 中 short_open_tag=On,重启 Apache 服务器即可 ASP 风格:<% 代码段; %>需要配置 PHP 配置文件 php.ini 中 asp_tags=On,重启 Apache 服务器即可 常量 & 变量定义常量 define($name, $value) const NAME=值</br>常量名称不加$常量名称最好大写,以字母或者下划线开始常量默认区分大小写常量作用域是全局常量一经定义,在脚本执行期间是不能改变的常量的值可以是标量类型,也可以是数组</br> - constant($name) //根据常量的名称获取常量的值- defined($name) //检测常量名称是否存在,如果存在返回true,否则返回false- get_defined_constants() //返回的是包含系统常量和自定义常量的数组 魔术常量__LINE__ //得到当前的行号__FILE__ //得到当前文件的完整绝对路径和文件名__DIR__ //得到文件的完整绝对路径__FUNCTION__ //得到当前函数的名称__CLASS__ //得到当前类的类名__METHOD__ //得到当前类的方法名称__TRAIT__ //得到当前的 TRAIT 名称__NAMESPACE__ //得到当前明明空间的名称 定义变量 通过美元$变量名称来表示变量 PHP 是弱类型语言,可以声明变量在使用,也可以不声明,可以一次声明一个,也可以一次声明多个 变量命名法 驼峰标记法小骆驼: firstName,lastName,zendControllerFront大骆驼: irstName,LastName,ZendControllerFront 下划线法first_name,last_name,zend_controller_front 预定义变量$GLOBALS //超全局变量,包含以下所有的预定义变量$_SERVERS //服务器和执行环境信息变量$_ENV //环境变量$_COOKIE //HTTP Cookies$_SESSION //HTTP Session 变量$_FILES //文件上传信息变量$_GET['名称'] //主要接收以?形式传递的数据,像表单以 get 形式发送数据,包括像超链接典型的?形式传递参数$_POST['名称'] //主要接收表单以 post 形式发送的数据$_REQUEST //$_GET+$_POST+$_COOKIE 数据类型 & 转换临时转换整型: (int)$变量名称|(integer)$变量名称浮点型: (float|double|real)$变量名称字符型: (string)$变量名称布尔型: (bool|boolean)$变量名称空: (unset)$变量名称数组: (array)$变量名称对象: (object)$变量名称 通过系统函数实现intval($var) //返回变量转换成整型之后的值floatval($var)|doubleval($var) //返回变量转换成浮点型的值strval($var) //返回变量转换成字符串的值boolval($var) //返回变量转换成布尔类型的值 永久转换settype($var,$type) //设置变量的类型gettype($var) //返回变量的类型 函数函数变量局部变量 局部动态变量: 变量只在函数内部执行,执行完毕则被销毁 局部静态变量: 在函数内部设置 static 时,执行完毕变量不被销毁 全局变量: 使用 global,在函数内部定义全局变量,当函数执行时先调用函数外面已经定义好的变量再执行,如函数内部有重复定义相同变量不同值,执行出的是函数内部修改过的值 参数传递 值传递: 在函数内部修改变量的值的情况下,在函数调用时调用函数外部的变量,值不变 引用传递: 在函数内部修改变量的值的情况下,在函数调用时,函数的参数前面加一个&符号,值发生改变 在对象中,不加&符号,对象的值也会发生改变堆内存: 存放占用内存比较大的,如对象 new xxx()栈内存: 存放基本类型 $obj 可变参数列表func_num_args:实参个数;func_get_arg:返回某一个实参,必须事实参数组的索引;func_get_args:返回实参数组;可以返回整型,字符串型,数组等数据类型 复杂函数类型可变函数:通过变量改变函数的名字并调用,让函数的调用更具有多样性 匿名函数:使用变量 = function(){}; ,调用时也是用变量加小括号来进行调用,变量后面要加上分号结尾声明一个函数不给函数起名字,用来以后做回调函数时用 嵌套函数访问外部局部变量:变量名 1 = function() use ($变量名 2){}; 系统库函数int strlen(string $str) //返回字符串长度string strtolower(string $str) //转换成小写string strtoupper(string $str) //转换成大写string ucfirst(string $str) //句首字母转换成大写string ucwords(string $str) //每个单词首字母转换成大写mixed str_replace(mixed $search, mixed replace, mixed $subject, [int &$count]) //实现字符替换,区分大小写mixed str_ireplace(mixed $search, mixed replace, mixed $subject, [int &$count]) //实现字符替换,不区分大小写float floor(float $svalue) //舍去float ceil(float $svalue) //进位int mt_rand(int $min, int $max) //随机数,比rand()更好 数组创建数组 通过 array()形式 array()空数组array(值,…)下标连续的索引数组,下标从 0 开始array(键名=>键值,…)指定下标的索引数组、关联数组、混合数组通过[]的形式定义数组,代替 array() 通过[ ]动态创建 $数组名称[]=值 //下标连续的索引数组$数组名称[键名]=值 //指定下标的索引数组和关联数组 通过 range()和 compact()快速创建 range() //快速创建下标连续的索引数组compact() //快速创建关联数组,只能写已经存在的变量名称,不能加$ 通过 define(), const 定义常量数组 数组转换临时转换: (array)$var永久转换: settype($var,$type) 数组运算符+ 合并数组,如果键名相同,使用前面数组的键值== 只比较键名和键值是否相同,如果相同返回 true,否则返回 false=== 既要比较键名和键值是否相同,还要比较类型和顺序 数组遍历通过 foreach 遍历数组foreach($数组名称 as $val){循环体;} //只要键值foreach($数组名称 as $key=>$val){循环体;} //既要键名又要键值foreach($数组名称 as $key=>&$val){循环体;} //引用传递 深入理解 PHP 原理之 foreach 可以通过:和 endforeach 代替{ } PHP7 中 foreach 的改变 foreach 遍历对数组内部指针不再起作用 按照值进行遍历的时候,foreach 操作的值是数组的副本 按照引用进行遍历的时候,有更好的迭代特性,在遍历体内修改数组对遍历有影响 通过指针函数遍历key($array) //得到当前指针所在位置的键名current($array) //得到当前指针所在位置的键值next($array) //将数组指针向下移动一位,返回当前指针所在位置的键值,否则返回falseprev($array) //将数组指针向上移动一位,返回当前指针所在位置的键值,否则返回 falseend($array) //将数组指针移动到末尾,返回当前指针所在位置的键值,否则返回falsereset($array) //将数组指针移动到开始,返回当前指针所在位置的键值,否则返回 false 通过 each()和 list()函数遍历数组each()list() 数组库 API创建数组操作range($min,$max[,$step=1]):快速创建下标连续的索引数组compact($varname,$varname...):快速创建关联数组array_fill($start_index,$num,$value):用给定的值填充数组array_fill_keys($keys,$value):使用指定的键和值填充数组array_combine($keys,$values):创建一个数组,用一个数组的值作为其键名,另外一个值作为其键值 键值相关操作count($var[,$mode=COUNT_NORMAL])/sizeof():计算数组中的单元数目或对象中的属性个数array_keys($array):取得数组的键名作为下标连续的索引数组返回array_values($array):取得数组的键值作为下标连续的索引数组返回array_flip($array):交换数组中的键名和键值in_array($search,$array[,$strict]):检测数组中是否存在某个值array_search($search,$array[,$strict]):在数组中搜索给定的值,如果成功则返回相应的键名array_key_exists($search,$array):检查给定的键名或索引是否存在于数组中array_reverse($array[,$preserve_keys=false]):数组倒置shuffle($array):打乱数组的元素array_rand($array[,$num_req=1]):随机取出数组的键名array_unique($array[,$sort_flag=SORT_STRING]):移除数组中重复的值array_sum($array):统计数组中元素值的总和array_product($array):计算数组中所有值的乘积array_count_values($array):统计数组中值出现的次数extract($array[,$extract_type=EXTR_OVERWRITE[,$prefix=null]]):从数组中将变量导入到当前的符号表array_pad($array,$size,$value):用值将数组填补到指定长度 数组指针函数key($array):得到当前指针所在位置元素的键名current($array)|pos($array):得到当前指针所在位置元素的键值next($array):将数组指针向下移动一位,并且返回当前指针所在位置元素的键值prev($array):将数组指针向上移动一位,并且返回当前指针所在位置元素的键值end($array):将数组指针移动倒数组的末尾,并且返回当前指针所在位置元素的键值reset($array):将数组指针移动到数组的开始,并且返回当前指针所在位置元素的键值each($array):返回数组中当前的键值对,并将数组指针向下移动一位list($var,...):将数组中元素的值赋给对应的变量array_unshift($array,$value...):在数组开头插入一个元素或者多个元素array_shift($array):弹出数组的第一个元素array_push($array,$value...):在数组末尾压入一个元素或者多个元素array_pop($array):弹出数组的最后一个元素 数组的排序函数sort($array[,$sort_flag=SORT_REGULAR]):对数组的键值按照升序排列,不保留键名rsort($array[,$sort_flag=SORT_REGULAR]):对数组键值按照降序排列,不保留键名asort($array[,$sort_flag=SORT_REGULAR]):对数组键值按照升序排列,保留键值对关系arsort($array[,$sort_flag=SORT_REGULAR]):对数组键值按照降序排列,保留键值对关系ksort($array[,$sort_flag=SORT_REGULAR]):对数组的键名按照升序排列krsort($array[,$sort_flag=SORT_REGULAR]):对数组的键名按照降序排列natsort($array):用自然排序法排序natcasesort($array):用自然排序算法对数组进行不区分大小写字母的排序array_multisort($arr[,$arg=SORT_STRING...]):对多个数组或多维数组进行排序 数组的交集与差集array_diff($array1,$array2[...]):计算数组的差集array_diff_assoc($array1,$array2[,...]):带索引检查计算数组的差集array_intersect($array1,$array2[...]):计算数组的交集array_intersect_assoc($array1,$array2[...]):带索引检查计算数组的交集 数组的拆分与合并array_slice($array,$offset[$length=null[,$preserve_keys=false]]):截取数组array_splice($array,$offset[,$length=0,$replacement]]):将数组中一部分去掉并用其它值替代array_merge($arr1[,$arr2...]):合并数组array_chunk($array,$size[,$preserve_keys=false]):将一个数组分割成多个array_column($array,$column_key[,$index_key]):返回数组中指定的一列 错误及常用命令 Parse error(解析错误): syntax error(语法错误), unexpected ‘<’, expecting end of file Notice(通知): Undefined variable(未定义的变量): sdkljflskdjflksdjflksdjfklj Catchable fatal(致命) error: Object of class stdClass could not be converted to string Warning(警告): settype(): Invalid(非法) type</br> header('content-type:text/html;charset=utf-8');date_defalut_timezone_set('PRC');echo($var,....) //输出一个或者多个字符串var_dump($var) //打印变量的详细信息,可以一次打印一个或者多个变量的详细信息print_r($var) //打印数组的信息unset($var,...) //销毁变量,可以一次销毁一个或者多个,销毁之后变量的值为nulltime() //返回当前的 Unix 时间戳is_[int|float|double|bool...]($var) //判断变量的类型isset() //检测变量是否存在function_exists() //判断函数谁否存在file_exists() //判断文件是否存在$var = file_get_contents($filename) //得到文件中的内容,返回的是字符串serialize() //产生一个可存储的值的表示unserialize() //从已存储的表示中创建 PHP 的值setcookie(string $name, string $value, int $expire = 0, string $path = "", string $domain = "") //设置coockie:$name名称 $value值 $expire生命周期 $path可用路径 $domain可用域名范围$var = strip_tags() //从字符串中去除 HTML 和 PHP 标记]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>php</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Adobe 2019 crack]]></title>
<url>%2F2018%2F11%2F01%2FAdobe2019%2F</url>
<content type="text"><![CDATA[  Adobe 2019 全家桶和破解包百度云链接,所有安装包和破解未验证具体完整性和安全性,可能出现不完全破解,请谨慎使用文章内容和链接非原创,在此感谢 vposy 胡萝卜周 和 painter 大神们,还有学校 摄影工作室 的小伙伴们。关于破解的最新内容会搬运过来同步更新,不一定及时,有需要可以去关注一下大神们微博:vposy,胡萝卜周,twitter:@painter701 2 月更新 转自微博 2.18 SP 版已更新,为 Illustrator CC 2019 添加了库功能。Photoshop CC 2019 直接支持视频模块,不再需要登录后激活 2.7 Adobe Lightroom Classic CC 8.2 2.6 Adobe Photoshop CC 2019 (20.0.3.24950) 2.4 CC 2018 WIN SP 版/大师版,CC 2019 WIN/MAC SP 版/大师版 1 月更新 1.31 Camera Raw CC 11.2.0.36 1.12 为 Animate、Dreamweaver、Illustrator、InCopy、InDesign、Lightroom Classic 添加了文件夹图标 1.10 Adobe Photoshop CC 2019 (20.0.2.22488) 12 月更新 12.22 AE16.0.1.48 修正 HEVC,建议按住 ctrl+alt+shift 启动程序重置一次 PR 修正主页 12.13 Adobe Acrobat Pro DC 2019 连续版 (2019.010.20064) SP 2018.12.13 更新 11 月更新 11.11 Lightroom Classic 8.0 要求重新登录,但不影响正常使用,功能完整。 11.8 Adobe Photoshop CC 2019.0.1 (20.0.1.17836) 11.2 更新 Adobe Bridge CC 2019.0.1 (9.0.1.216) 更新 Adobe InDesign CC 2019.0.1 (14.0.1.202) 更新 Adobe Media Encoder CC 2019.0.1 (13.0.1.12) 更新 Adobe Premiere Pro CC 2019.0.1 (13.0.1.13) 到 10 月 28 日,目前除 Lightroom Classic CC 没有照片编辑功能外,vposy 破解的版本其它貌似都能勉勉强强使用,具体会出现的 BUG 和解决方案也会持续更新出来(如果有的话)下载链接vposy 的原版和 SP 版(只有 win10)百度云下载链接:https://pan.baidu.com/share/init?surl=F1iCpjajAz-Ez5QsJZP5zQhttps://pan.baidu.com/s/1F1iCpjajAz-Ez5QsJZP5zQ提取密码: ewyu vposy 的 Adobe CC 2018 大师版百度云下载链接:https://pan.baidu.com/s/1dio1Z4提取密码:w7i4 ZerOCod3 文件替换破解 百度云下载链接:https://pan.baidu.com/s/11msujRxnXgl5wJpHNjd6YA提取码: xjew 破解文件为.exe 文件,将 Adobe 根目录下的文件替换成破解文件就行 或者可以下载 ZerOCod 破解包合集。https://pan.baidu.com/s/1W3Jnd8w2wMLTVHlsrvYQhw 提取码: zi2u CC Maker 早期版本汇总 百度云下载链接:链接: https://pan.baidu.com/s/14ubOSVQkltVFarvbB7vUXQ提取码: cuvr CC Maker 汇总了早期版本的 Adobe 软件下载,早期版本可用 amtlib 破解程序破解 关于 Adobe CC 2019 系统需求 WIN10 最新版本。旧版 WIN10,WIN8.1 不支持,WIN7 部分支持(不建议) CC2019 开始 ADOBE 抛弃了十几年的 amtlib,新激活模块内置于主程序,正版必须登录 ID,所有之前的破解程序都没用,新版本的破解也只是是跳过 ID 登录,没有授权信息 WIN 新版破解会很快,但 MAC 版短时间就难说了。全系列完美破解短时间就不要想了,只有本地功能,与 ACC 有关的在线功能如库能否正常使用取决于 ADOBE。ACC 需单独破解 官方今年还没有给出完整版地址,同时也封掉了 CCP。新版版发布时间还不长,不清楚官方是否不打算给完整包了。 新版本 BUG 问题可以去 Adobe 官方社区论坛上讨论 painter 的 emu 他本人说遇到了一点困难,至少目前没有 至少他是想在尽量不动主程序的情况下模拟 ID 授权激活的,而不是简单的跳过 ID 登录,完全规避无授权 BUG,具体情况可以自己去推上问他]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>others</tag>
</tags>
</entry>
<entry>
<title><![CDATA[breast-cancer-diagnose from Kaggle]]></title>
<url>%2F2018%2F10%2F28%2Fcancer-diagnose%2F</url>
<content type="text"><![CDATA[人工智能课程作业,乳腺癌检测(from Kaggle)。作业训练基础的数据清理,数据特征分类,验证不同的分类算法之间的分类效果 训练数据集:[Breast Cancer Wisconsin (Diagnostic) Data Set](https://archive.ics.uci.edu/ml/datasets/Breast+Cancer+Wisconsin+%28Diagnostic%29) UCI 关于此数据集有两份,本实验使用较为完整的一份 实验数据为文本数据,数据量是为 569 的小型数据,有部分数据缺失 步骤中降维部分,violin 图部分为半成品,效果并不显著,可以自动忽略 Attribute Information: ID number Diagnosis (M = malignant, B = benign) Ten real-valued features are computed for each cell nucleus:a) radius (mean of distances from center to points on the perimeter)b) texture (standard deviation of gray-scale values)c) perimeterd) areae) smoothness (local variation in radius lengths)f) compactness (perimeter^2 / area - 1.0)g) concavity (severity of concave portions of the contour)h) concave points (number of concave portions of the contour)i) symmetryj) fractal dimension (“coastline approximation” - 1) 以下列举部分实验结果,具体实现步骤>> breast-cancer-diagnose.ipynb download LogisticRegression (逻辑斯蒂回归 分类器)from sklearn.linear_model import LogisticRegressionLR = LogisticRegression()LR.fit(X_train, y_train)LR.predict(X_test)LR.score(X_test,y_test) Out: 0.9883040935672515 结论: 通过比较,逻辑斯蒂模型比随机梯度下降模型在测试集上表现有更高的准确性,因为逻辑斯蒂采用解析的方式精确计算模型参数,而随机梯度下降采用估计值 特点分析: 逻辑斯蒂对参数的计算采用精确解析的方法,计算时间长但是模型性能高,随机梯度下降采用随机梯度上升算法估计模型参数,计算时间短但产出的模型性能略低,一般而言,对于训练数据规模在 10 万量级以上的数据,考虑到时间的耗用,推荐使用随机梯度算法 SGDClassifier (梯度下降 分类器)from sklearn.linear_model import SGDClassifier SGD = SGDClassifier(loss='hinge', penalty='l2', alpha=0.001, l1_ratio=0.15, fit_intercept=True, max_iter=None, tol=None, shuffle=True, verbose=0, epsilon=0.1, n_jobs=1, random_state=None, learning_rate='optimal', eta0=0.0, power_t=0.5, class_weight=None, warm_start=False, average=False, n_iter=None)SGD.fit(X_train,y_train)SGD.predict(X_test)SGD.score(X_test,y_test) Out: 0.9824561403508771 LinearRegression (线性回归 分类器)from sklearn.linear_model import LinearRegression LR2 = LinearRegression(fit_intercept=True, normalize=False, copy_X=True, n_jobs=1)LR2.fit(X_train,y_train)LR2.predict(X_test)LR2.score(X_test,y_test) Out: 0.8739645029687063 KNeighborsClassifier (k 近邻 分类器)from sklearn.neighbors import KNeighborsClassifier KNN = KNeighborsClassifier(n_neighbors=5, weights='uniform', algorithm='auto', leaf_size=30, p=2, metric='minkowski', metric_params=None, n_jobs=1, **kwargs)KNN.fit(X_train,y_train)KNN.predict(X_test)KNN.score(X_test,y_test) Out: 0.9883040935672515 GaussianNB (朴素贝叶斯 分类器)from sklearn.naive_bayes import GaussianNB GNB = GaussianNB(priors=None)GNB.fit(X_train,y_train)GNB.predict(X_test)GNB.score(X_test,y_test) Out: 0.9766081871345029]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Kaggle</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Thinkpad fingerprint device on Linux]]></title>
<url>%2F2018%2F10%2F28%2Ftp-print%2F</url>
<content type="text"><![CDATA[Thinkpad 在 Linux 下新版本指纹识别驱动的安装与指纹实现管理员验证 1.Check your finger print devicelsusb example in device ID: 138:0090 and show device ID (for me) Bus xxx Device xxx: ID 138a:0090 Validity Sensors, Inc. here are some integrated fingerprint Reader in thinkwiki USB ID Reader Software 08ff:1600 Authentec AES1610 fprint 08ff:2580 Authentec AES2501 fprint 08ff:2810 Authentec 2810 supported by libfprint v0.5.0 onwards released December 2012 138a:0017 Validity Sensors, Inc. Fingerprint Reader (to test) Driver Patch as use case with T440 or gist sample Supported by libfprint v0.6.0 138a:0090 Validity Sensors RE work for validity90 fingerprint reader 2.Install packages 2.1 Packages for Fingerprint GUI for Ubuntu 14.04, 16.04, 17.10, 18.04 and any distribution based thereupon ! check if your device is in supported readers then install 2.2 Install fprintd (for me in device 138a:0090) read the guide: Validity and libfprint in github for ubuntu/linuxmint sudo apt install fpirntdsudo add-apt-repository -y ppa:3v1n0/libfprint-vfs0090sudo apt updatesudo apt install libpam-fprintd for archlinux sudo pacman -S fprintdyaourt -S libfprint-vfs0090-git 3.Enroll your finger print add your signature for a finger (touch your finger device) fprintd-enroll ! use sudo fprintd-enroll may have some bug if not work for finger in {left,right}-{thumb,{index,middle,ring,little-finger}; do fprintd-enroll -f "$finger" "$USER"; done e.g for finger in {left,right}-{thumb,{index,middle,ring,little-finger}; do fprintd-enroll -f "right-index-finger" "kevin"; done ! here has a bug, you may need to add 10x4 times to add finger signature 4.Login configuration read the guide in archlinux wiki 4.1 For linuxmint Add pam_fprintd.so as sufficient to the top of the auth section of /etc/pam.d/runuser sudo nano /etc/pam.d/runuser---auth sufficient pam_fprintd.soauth sufficient pam_rootok.sosession optional pam_keyinit.so revoke... 4.2 For archlinux Add pam_fprintd.so as sufficient to the top of the auth section of /etc/pam.d/system-local-login 5.Reboot check the light of finger device in linuxmint, print finger then click sign in in archlinux, click enter then print finger]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>Linux_device</tag>
</tags>
</entry>
<entry>
<title><![CDATA[PHP & MySQL learning notes (1)]]></title>
<url>%2F2018%2F10%2F28%2Fw3school-php%2F</url>
<content type="text"><![CDATA[W3school PHP 和 MySQL 的初次学习包括 PHP 基础语法,表单处理,PHP 连接 MySQL 数据库操作 1.PHP 基础PHP 脚本以 <?php 开头,以 ?> 结尾,语句以分号结尾: <?php// 此处是 PHP 代码;?> // 这是单行注释 # 这也是单行注释 /* */这是多行注释块 变量 变量以 $ 符号开头,其后是变量的名称 变量名称必须以字母或下划线开头 变量名称不能以数字开头 变量名称只能包含字母数字字符和下划线 A-z、0-9 以及 _ 变量名称对大小写敏感($y 与 $Y 是两个不同的变量) 松散型语言,不必告知 PHP 变量的数据类型 PHP global 关键词 global 关键词用于访问函数内的全局变量。 要做到这一点,请在(函数内部)变量前面使用 global 关键词 PHP 同时在名为 $GLOBALS[index] 的数组中存储了所有的全局变量。 function myTest() { global $x,$y; $y=$x+$y;}function myTest() { $GLOBALS['y']=$GLOBALS['x']+$GLOBALS['y'];} PHP static 关键词 通常,当函数完成/执行后,会删除所有变量。不过,有时我需要不删除某个局部变量。实现这一点需要更进一步的工作。要完成这一点,请在您首次声明变量时使用 static 关键词 echo 和 print 之间的差异: echo - 能够输出一个以上的字符串 print - 只能输出一个字符串,并始终返回 1 PHP var_dump() 会返回变量的数据类型和值 PHP 对象 对象是存储数据和有关如何处理数据的信息的数据类型。 首先我们必须声明对象的类。对此,我们使用 class 关键词;然后我们在对象类中定义数据类型;然后在该类的实例中使用此数据类型 class Car{ var $color; function Car($color="green") { $this->color = $color; } function what_color() { return $this->color; }} strlen() 函数返回字符串的长度,以字符计 strpos() 函数用于检索字符串内指定的字符或文本 如需设置常量,请使用 define() 函数 - 它使用三个参数: 首个参数定义常量的名称 第二个参数定义常量的值 可选的第三个参数规定常量名是否对大小写不敏感。默认是 false。 PHP 字符串运算符 运算符 名称 例子 结果 . 串接 $txt1 = “Hello” $txt2 = $txt1 . “ world!” 现在 $txt2 包含 “Hello world!” .= 串接赋值 $txt1 = “Hello” $txt1 .= “ world!” 现在 $txt1 包含 “Hello world!” PHP 递增/递减运算符 运算符 名称 描述 ++$x 前递增 $x 加一递增,然后返回 $x $x++ 后递增 返回 $x,然后 $x 加一递增 —$x 前递减 $x 减一递减,然后返回 $x $x— 后递减 返回 $x,然后 $x 减一递减 在 PHP 中, array() 函数用于创建数组 在 PHP 中,有三种数组类型: 索引数组 - 带有数字索引的数组$cars=array("Volvo","BMW","SAAB"); 关联数组 - 带有指定键的数组$age=array("Peter"=>"35","Ben"=>"37","Joe"=>"43"); 多维数组 - 包含一个或多个数组的数组 count() 函数用于返回数组的长度(元素数) 如需遍历并输出索引数组的所有值,您可以先 count 数组长度,再使用 for 循环 如需遍历并输出关联数组的所有值,您可以使用 foreach 循环 PHP foreach 循环 foreach 循环只适用于数组,并用于遍历数组中的每个键/值对。 foreach ($array as $value) {code to be executed;} PHP - 数组的排序函数 sort() - 以升序对数组排序 rsort() - 以降序对数组排序 asort() - 根据值,以升序对关联数组进行排序 ksort() - 根据键,以升序对关联数组进行排序 arsort() - 根据值,以降序对关联数组进行排序 krsort() - 根据键,以降序对关联数组进行排序 超全局变量: $GLOBALS 引用全局作用域中可用的全部变量$_SERVER 保存关于报头、路径和脚本位置的信息$_REQUEST 用于收集 HTML 表单提交的数据$_POST 广泛用于收集提交 method="post" 的 HTML 表单后的表单数据。$_POST 也常用于传递变量$_GET 用于收集提交 HTML 表单 (method="get") 之后的表单数据,也可以收集 URL 中的发送的数据$_ENV$_COOKIE$_SESSION <html><body><form method="post" action="<?php echo $_SERVER['PHP_SELF'];?>">Name: <input type="text" name="fname"><input type="submit"></form><?php$name = $_REQUEST['fname'];echo $name;?></body></html> 2.PHP 表单HTML 表单处理表单界面 <html><body><!--form创建表单--><form action="welcome.php" method="post">Name: <input type="text" name="name"><br> <!--文本-->E-mail: <input type="text" name="email"><br>Gender: <!--选择--><input type="radio" name="gender" value="female">Female<input type="radio" name="gender" value="male">Male<input type="submit"></form></body></html> welcome.PHP <html><body>Welcome <?php echo $_POST["name"]; ?><br>Your email address is: <?php echo $_POST["email"]; ?></body></html> 可以将 post 换成 get 后端 GET & POST $_GET 是通过 URL 参数传递到当前脚本的变量数组。 通过 GET 方法从表单发送的信息对任何人都是可见的(所有变量名和值都显示在 URL 中)。GET 对所发送信息的数量也有限制。限制在大于 2000 个字符。不过,由于变量显示在 URL 中,把页面添加到书签中也更为方便。 GET 可用于发送非敏感的数据。 $_POST 是通过 HTTP POST 传递到当前脚本的变量数组。 通过 POST 方法从表单发送的信息对其他人是不可见的(所有名称/值会被嵌入 HTTP 请求的主体中),并且对所发送信息的数量也无限制。 一般偏向于 POST 发送表单数据 表单安全验证<form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> $_SERVER["PHP_SELF"] 是一种超全局变量,它返回当前执行脚本的文件名 htmlspecialchars() 函数把特殊字符转换为 HTML 实体 $_SERVER["PHP_SELF"] 变量能够被黑客利用,使用了 PHP_SELF,用户能够输入下划线然后执行跨站点脚本(XSS),通过使用 htmlspecialchars() 函数能够避免 $_SERVER["PHP_SELF"] 被利用 利用 php 函数检查表单 (通过 PHP trim() 函数)去除用户输入数据中不必要的字符(多余的空格、制表符、换行) (通过 PHP stripslashes() 函数)删除用户输入数据中的反斜杠(\) // 定义变量并设置为空值$name = $email = $gender = $comment = $website = "";if ($_SERVER["REQUEST_METHOD"] == "POST") { $name = test_input($_POST["name"]); $email = test_input($_POST["email"]); $website = test_input($_POST["website"]); $comment = test_input($_POST["comment"]); $gender = test_input($_POST["gender"]);}function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data;} 必须输入字段增加了一些新变量:$nameErr、$emailErr、$genderErr 以及 $websiteErr。这些错误变量会保存被请求字段的错误消息。 还需要每个 $_POST 变量添加了一个 if else 语句。这条语句检查 $_POST 变量是否为空(通过 PHP empty() 函数)。如果为空,则错误消息会存储于不同的错误变量中。如果不为空,则通过 test_input() 函数发送用户输入数据 $nameErr = $emailErr = $genderErr = $websiteErr = "";$name = $email = $gender = $comment = $website = "";if ($_SERVER["REQUEST_METHOD"] == "POST") { if (empty($_POST["name"])) { $nameErr = "Name is required"; } else { $name = test_input($_POST["name"]); } if (empty($_POST["email"])) { $emailErr = "Email is required"; } else { $email = test_input($_POST["email"]); } if (empty($_POST["website"])) { $website = ""; } else { $website = test_input($_POST["website"]); } if (empty($_POST["comment"])) { $comment = ""; } else { $comment = test_input($_POST["comment"]); } if (empty($_POST["gender"])) { $genderErr = "Gender is required"; } else { $gender = test_input($_POST["gender"]); }} HTML 显示错误消息在每个被请求字段后面增加了一点脚本。如果需要,会生成恰当的错误消息 Name: <input type="text" name="name"><span class="error">* <?php echo $nameErr;?></span> //验证E-mail:<input type="text" name="email"><span class="error">* <?php echo $emailErr;?></span>Website:<input type="text" name="website"><span class="error"><?php echo $websiteErr;?></span><br><br><label>Comment: <textarea name="comment" rows="5" cols="40"></textarea>Gender:<input type="radio" name="gender" value="female">Female<input type="radio" name="gender" value="male">Male<span class="error">* <?php echo $genderErr;?></span><input type="submit" name="submit" value="Submit"> 验证输入数据验证名字:preg_match() 函数检索字符串的模式,如果模式存在则返回 true,否则返回 false $name = test_input($_POST["name"]);if (!preg_match("/^[a-zA-Z ]*$/",$name)) { $nameErr = "只允许字母和空格!";} 验证 email $email = test_input($_POST["email"]);if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)) { $emailErr = "无效的 email 格式!";} 验证 URL $website = test_input($_POST["website"]);if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website)) { $websiteErr = "无效的 URL";} HTML 保留表单中的值在输入字段的 value 属性中增加了一小段 PHP 脚本:name、email 以及 website 在 comment 文本框字段中,把脚本放到了 <textarea> 与 </textarea> 之间;这些脚本输出 $name、$email、$website 和 $comment 变量的值。 要显示选中了哪个单选按钮,操作 checked 属性(而非单选按钮的 value 属性) Name: <input type="text" name="name" value="<?php echo $name;?>">E-mail: <input type="text" name="email" value="<?php echo $email;?>">Website: <input type="text" name="website" value="<?php echo $website;?>">Comment: <textarea name="comment" rows="5" cols="40"><?php echo $comment;?></textarea>Gender:<input type="radio" name="gender"<?php if (isset($gender) && $gender=="female") echo "checked";?>value="female">Female<input type="radio" name="gender"<?php if (isset($gender) && $gender=="male") echo "checked";?>value="male">Male 完整代码<!DOCTYPE HTML><html><head><style>.error {color: #FF0000;}</style></head><body><?php// 定义变量并设置为空值$nameErr = $emailErr = $genderErr = $websiteErr = "";$name = $email = $gender = $comment = $website = "";if ($_SERVER["REQUEST_METHOD"] == "POST") { if (empty($_POST["name"])) { $nameErr = "姓名是必填的"; } else { $name = test_input($_POST["name"]); // 检查姓名是否包含字母和空白字符 if (!preg_match("/^[a-zA-Z ]*$/",$name)) { $nameErr = "只允许字母和空格"; } } if (empty($_POST["email"])) { $emailErr = "电邮是必填的"; } else { $email = test_input($_POST["email"]); // 检查电子邮件地址语法是否有效 if (!preg_match("/([\w\-]+\@[\w\-]+\.[\w\-]+)/",$email)) { $emailErr = "无效的 email 格式"; } } if (empty($_POST["website"])) { $website = ""; } else { $website = test_input($_POST["website"]); // 检查 URL 地址语法是否有效(正则表达式也允许 URL 中的斜杠) if (!preg_match("/\b(?:(?:https?|ftp):\/\/|www\.)[-a-z0-9+&@#\/%?=~_|!:,.;]*[-a-z0-9+&@#\/%=~_|]/i",$website)) { $websiteErr = "无效的 URL"; } } if (empty($_POST["comment"])) { $comment = ""; } else { $comment = test_input($_POST["comment"]); } if (empty($_POST["gender"])) { $genderErr = "性别是必选的"; } else { $gender = test_input($_POST["gender"]); }}function test_input($data) { $data = trim($data); $data = stripslashes($data); $data = htmlspecialchars($data); return $data;}?><h2>PHP 验证实例</h2><p><span class="error">* 必需的字段</span></p><form method="post" action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]);?>"> 姓名:<input type="text" name="name"> <span class="error">* <?php echo $nameErr;?></span> <br><br> 电邮:<input type="text" name="email"> <span class="error">* <?php echo $emailErr;?></span> <br><br> 网址:<input type="text" name="website"> <span class="error"><?php echo $websiteErr;?></span> <br><br> 评论:<textarea name="comment" rows="5" cols="40"></textarea> <br><br> 性别: <input type="radio" name="gender" value="female">女性 <input type="radio" name="gender" value="male">男性 <span class="error">* <?php echo $genderErr;?></span> <br><br> <input type="submit" name="submit" value="提交"></form><?phpecho "<h2>您的输入:</h2>";echo $name;echo "<br>";echo $email;echo "<br>";echo $website;echo "<br>";echo $comment;echo "<br>";echo $gender;?></body></html> 3.mySQLPHP 连接 MySQL通过 mysql_connect() 函数完成 mysql_connect('servername','username','password'); 参数 描述 servername 可选。规定要连接的服务器。默认是 “localhost:3306” username 可选。规定登录所使用的用户名。默认值是拥有服务器进程的用户的名称 password 可选。规定登录所用的密码。默认是 “” $con = mysql_connect("localhost","root","");if (!$con) { die('Could not connect: ' . mysql_error()); //连接失败执行die } 创建数据库用 mysql_query() 函数 mysql_query("CREATE DATABASE database_name",password) $con = mysql_connect('localhost','root','');if (!$con){ die('Could not connect: ' . mysql_error()); }if (mysql_query("CREATE DATABASE my_db",$con)){ //创建数据库 echo "Database created"; }else{ echo "Error creating database: " . mysql_error(); }mysql_close($con); 创建表创建表之前,必须首先选择数据库;通过 mysql_select_db() 函数选取数据库mysql_query() 函数添加 CREATE TABLE 语句 // Create table in databasemysql_select_db("DATABASE NAME", $con);$sql = "CREATE TABLE Persons(FirstName varchar(15),LastName varchar(15),Age int)";mysql_query($sql,$con); 表的主键和递增字段:主键字段通常是 ID 号,且通常使用 AUTO_INCREMENT 设置 AUTO_INCREMENT 会在新记录被添加时逐一增加该字段的值。要确保主键字段不为空,我们必须向该字段添加 NOT NULL 设置 personID int NOT NULL AUTO_INCREMENT 插入数据INSERT INTO table_name VALUES (value1, value2,....) SQL 语句对大小写不敏感。INSERT INTO 与 insert into 相同。 为了让 PHP 执行该语句,我们必须使用 mysql_query() 函数。该函数用于向 MySQL 连接发送查询或命令 mysql_select_db("DATABASE NAME", $con);mysql_query("INSERT INTO Persons (FirstName, LastName, Age)VALUES ('Peter', 'Griffin', '35')");mysql_close($con); 表单数据插入数据库 当用户点击上例中 HTML 表单中的提交按钮时,表单数据被发送到 “insert.php”。”insert.php” 文件连接数据库,并通过 $_POST 变量从表单取回值。然后,mysql_query() 函数执行 INSERT INTO 语句,一条新的记录会添加到数据库表中 mysql_select_db("DATABASE NAME", $con);$sql="INSERT INTO Persons (FirstName, LastName, Age)VALUES('$_POST[firstname]','$_POST[lastname]','$_POST[age]')"; //HTML表单中的数据if (!mysql_query($sql,$con)){die('Error: ' . mysql_error());}echo "1 record added";mysql_close($con) 查询数据SELECT column_name(s) FROM table_name 使用 mysql_fetch_array() 函数以数组的形式从记录集返回第一行 使用了 PHP 的 $row 变量 ($row[‘FirstName’] 和 $row[‘LastName’])输出每行的值 mysql_select_db("my_db", $con);$result = mysql_query("SELECT * FROM Persons");while($row = mysql_fetch_array($result)) { echo $row['FirstName'] . " " . $row['LastName']; echo "<br />"; }mysql_close($con); 显示成表格样式 mysql_select_db("my_db", $con);$result = mysql_query("SELECT * FROM Persons");echo "<table border='1'> <tr> <th>Firstname</th> <th>Lastname</th> </tr>"; while($row = mysql_fetch_array($result)) { echo "<tr>"; echo "<td>" . $row['FirstName'] . "</td>"; echo "<td>" . $row['LastName'] . "</td>"; echo "</tr>"; }echo "</table>";mysql_close($con); 如需选取匹配指定条件的数据,请向 SELECT 语句添加 WHERE 子句 SELECT column FROM table WHERE column operator value mysql_select_db("my_db", $con);$result = mysql_query("SELECT * FROM PersonsWHERE FirstName='Peter'"); ORDER BY 关键词用于对记录集中的数据进行排序 SELECT column_name(s) FROM table_name ORDER BY column_name ORDER BY 关键词,记录集的排序顺序默认是升序;可用 DESC 关键词来设定降序排序 SELECT column_name(s) FROM table_name ORDER BY column_name DESC mysql_select_db("my_db", $con);$result = mysql_query("SELECT * FROM Persons ORDER BY age"); 修改数据UPDATE 语句用于在数据库表中修改数据 UPDATE table_name SET column_name = new_value WHERE column_name = some_value mysql_select_db("my_db", $con);mysql_query("UPDATE Persons SET Age = '36'WHERE FirstName = 'Peter' AND LastName = 'Griffin'");mysql_close($con); 删除数据DELETE FROM 语句用于从数据库表中删除记录 DELETE FROM table_name WHERE column_name = some_value mysql_select_db("my_db", $con);mysql_query("DELETE FROM Persons WHERE LastName='Griffin'");mysql_close($con);]]></content>
<categories>
<category>study</category>
</categories>
<tags>
<tag>php</tag>
<tag>mysql</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Hexo的欢迎界面]]></title>
<url>%2F2018%2F10%2F28%2Fhello-hexo%2F</url>
<content type="text"><![CDATA[description: 这是第一次是使用 Hexo 时 Hexo 展示的页面,为方便查询移动至此Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post$ hexo new "My New Post" More info: Writing Run server$ hexo server More info: Server Generate static files$ hexo generate More info: Generating Deploy to remote sites$ hexo deploy More info: Deployment]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[tips about building blog]]></title>
<url>%2F2018%2F10%2F20%2Ftips-about-building-blog%2F</url>
<content type="text"><![CDATA[安装 hexo 的笔记,不间断进行更新更新目录: 安装和部署必要模组 页面模板 写文章 本地查看和 Github 部署 分类和标签须知 标签插件 建立资源文件夹 更换 Maupassant 主题 增加右下角动图 添加 pdf 插件 安装字数统计插件 安装 mathjax 公式支持 install nodejs npm git hexo 安装和部署必要模组install on Linuxsudo apt-get install -y nodejssudo apt-get install -y build-essentialsudo apt-get install -y npmsudo apt-get install git related modules npm install //install necessary componentsnpm install hexo-deployer-git --save // deploy to gitnpm install hexo-generator-feed --save // build RSSnpm install hexo-generator-sitemap --save // build sitemap deploy hexo open terminal & cd to the right direction mkdir blognpm install hexo -ghexo -v //check infohexo init //initialize folderhexo g //Start processing add ssh keyssh-keygen -t rsa -C "your email address"cat /home/xxx/.ssh/id_rsa.pub //check your key load key to Github (default on Github & default you can use Github) ssh -T [email protected] set id & emailgit config --global user.name "your id"git config --global user.email "your email" install on Windows download nodejs and install download git and install Win+R open cmd to the right direction mkdir blognpm install hexo -ghexo -v //check infonpm install //install necessary componentshexo init //initialize folderhexo g //Start processing add related module & ssh key & set id+email (the same as linux) template 模板 各页面相对应的模板名称 模板 用途 回退 index 首页 post 文章 index page 分页 index archive 归档 index category 分类归档 archive tag 标签归档 archive write pages 写文章init pagehexo new post "post_name" edittitle:date:categories:tags:description:###### tags 目前的标签 | Kaggle | Linux device | hexo | php | mysql | others | categories 目前的分类 Adobe: about any update & crack of CC software notes: personal thoughts & ideas others: just others study: study notes local server & deploy 本地查看和部署hexo clean //clean cachehexo generate //generate static fileshexo seserver //localhost:4000hexo deploy //open server update notes 2019.2.14 更新 categories & tags 分类和标签须知 只有文章支持分类和标签 分类具有顺序性和层次性,标签没有顺序和层次 Hexo 不支持指定多个同级分类 categories:- Diarytags:- PS3- Games Tag Plugins 标签插件quote 在文章中插入引言,可包含作者、来源和标题 {% blockquote [author[, source]] [link] [source_link_title] %}content{% endblockquote %} example {% blockquote David Levithan, Wide Awake %}Do not just seek happiness for yourself. Seek happiness for all. Through kindness. Through mercy.{% endblockquote %} Do not just seek happiness for yourself. Seek happiness for all. Through kindness. Through mercy. David LevithanWide Awake code 插入代码{% codeblock [title] [lang:language] [url] [link text] %}code snippet{% endcodeblock %} image 插入图片{% img [class names] /path/to/image [width] [height] [title text [alt text]] %} link 插入链接{% link text url [external] [title] %} Assert fold 资源文件夹 如果需要插入图片,最简单的方法就是将它们放在 source/pic 文件夹中。然后通过类似于 ![](/images/image.jpg) 的方法访问它们. 通过常规的 markdown 语法和相对路径来引用图片和其它资源可能会导致它们在存档页或者主页上显示不正确。需要使用标签插件 {% asset_img example.jpg This is an example image %}{% asset_path slug %}{% asset_img slug [title] %}{% asset_link slug [title] %}... 2.18 日更新 因 NexT 不可描述的页面无法跳转原因,更换主题到 Maupassant,大道至简 给文章添加目录:开头加上 toc: true 首页自定义显示文章摘录:在摘录后加上<!--more--> 2.22 日更新 增加萌宠或二次元动图hexo live2d 插件 2.0Github 地址 npm install --save hexo-helper-live2d然后挑一个npm install live2d-widget-model-xxxxx 向 Hexo 的 _config.yml 文件添加配置 live2d: enable: true scriptFrom: local pluginRootPath: live2dw/ pluginJsPath: lib/ pluginModelPath: assets/ tagMode: false debug: false model: use: live2d-widget-model-xxxxx display: position: right width: 150 height: 300 mobile: show: true 添加 pdf 插件npm install --save hexo-pdfhexo new page book .md 文件中添加 pdf 外部链接:{% pdf http://xxx.pdf %}本地连接:{% pdf ./pdf名字.pdf %} 安装字数统计插件npm i --save hexo-wordcount将自己所用主题中的 _config.yml 文件中的 wordcount 设置为 true 增加 instagram 链接npm install hexo-tag-instagram --save {% instagram post-url %}or{% instagram BXkz1bYB1-N %}or{% instagram false 50% https://www.instagram.com/p/BXkz1bYB1-N/ %} 7.29 日更新 安装 mathjax 支持安装 kramed(marked 修改版)npm uninstall hexo-renderer-marked --savenpm install hexo-renderer-kramed --save 更改/node_modules/hexo-renderer-kramed/lib/renderer.js function formatText(text) { // Fit kramed's rule: $$ + \1 + $$ //return text.replace(/`\$(.*?)\$`/g, '$$$$$1$$$$'); return text} 停止使用 hexo-math,改为 hexo-renderer-mathjaxnpm uninstall hexo-math --savenpm install hexo-renderer-mathjax --save 打开/node_modules/hexo-renderer-mathjax/mathjax.html 更新 CDN<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script> 在博客头部说明中开启Mathjax: true 使用时要注意_的转义 2020.11.26 更新 重启博客项目,修改分类为:code,language-learning,notes,paper,repo,study 标签增加到:algorithm others Vue book boosting c++ Kaggle sklearn flask time_series ensemble_learning bp_nn hexo python JavaScript bootstrap2.0 php laravel machine_learning mysql pandas session cookie slam Linux_device log Reference hexo.io cnblogs: hexo+Github 搭建自己的博客]]></content>
<categories>
<category>notes</category>
</categories>
<tags>
<tag>hexo</tag>
</tags>
</entry>
<entry>
<title><![CDATA[Welcome to Kevin_W's attic,filled with whispers & murmurs]]></title>
<url>%2F2018%2F10%2F10%2Fhello-world%2F</url>
<content type="text"><![CDATA[Kevin_W 创立于这个世界在 10 月 10 日,2018。 他可以是一本日志,也可以是一篇日记,一个仓库,或者一个告解室,一个树洞,亦或什么都不是。 但这里,的确是独立于外部的一个世界。 Kevin 不清楚这个世界能存在多久,会放置些什么,有多少谁在看,更新频率是多快,更新的知识有多深奥,只能保证这个世界创造的一切,都是十分重要的信息。 Kevin 也不清楚能把这个世界创造得多好,不清楚这个世界会往哪里发展,不清楚到底有多少个类似这样的平行世界,只能保证创造这个世界的 Kevin 是最 Kevin’s 的一个 Kevin. Wubba lubba dub dubHey,what are you in for ?]]></content>
<categories>
<category>notes</category>
</categories>
</entry>
</search>