-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsearch.xml
More file actions
316 lines (150 loc) · 55.1 KB
/
Copy pathsearch.xml
File metadata and controls
316 lines (150 loc) · 55.1 KB
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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>「React學習之路」Day3.學習基礎ES6(二)</title>
<link href="/2020/01/19/Introduction-and-Practice-React-Day-3/"/>
<url>/2020/01/19/Introduction-and-Practice-React-Day-3/</url>
<content type="html"><![CDATA[<h3 id="定義類別一Class"><a class="header-anchor" href="#定義類別一Class"></a>定義類別一Class</h3><p>在過去JavaScript就有一些類似於Class的語法,為什麼說類似?因為JavaScript中並沒有Class的概念。像是new或者instanceof的功能都是藉由動態物件所模擬出來的。</p><p>在ES6出現以前,都是藉由建構式來作為類別,之後透過new來產生實例。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">function example(text) {</span><br><span class="line"> this.text = text;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">example.prototype.run = function() {</span><br><span class="line"> console.log('Go !' + this.text)</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">var test = new example('Pokemon');</span><br><span class="line">test.run();</span><br></pre></td></tr></table></figure><p>上下兩個語法做的事情,其實都是一樣的,只是很明顯的下面這段ES6的語法更像物件導向的語法方式。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">class example4 {</span><br><span class="line"> constructor(text) {</span><br><span class="line"> this.text = 'test';</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> run() {</span><br><span class="line"> console.log("Go!" + this.text)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">const test44 = new example4('Pokemon');</span><br><span class="line">test44.run();</span><br></pre></td></tr></table></figure><h3 id="Getter和Setter"><a class="header-anchor" href="#Getter和Setter"></a>Getter和Setter</h3><p>在ES6內的Class也是有Getter和Setter的方法</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">class example {</span><br><span class="line"> constructor() {</span><br><span class="line"> </span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> set text(test) {</span><br><span class="line"> console.log("Setter! " + test)</span><br><span class="line"> this.test = text;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> get text() {</span><br><span class="line"> console.log("Getter! " + this.test)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">const test = new example();</span><br><span class="line">test.text = '123123'</span><br></pre></td></tr></table></figure><p>比較需要注意的是setter的名字如果跟內部宣告的變數名字相同的話,會造成無窮迴圈的狀況,所以這點要特別注意。如果是為了辨別,那麼可以在變數前面加 「 _ 」,例如 _text。</p><h3 id="繼承"><a class="header-anchor" href="#繼承"></a>繼承</h3><p>ES6中的Class也有extends關鍵字來實作類別繼承這項功能,但內部實作的原理還是基於原型鏈完成的。繼承父類別的子類別必須在constructor中呼叫「super」方法,「super」方法其實就是父類別的constructor方法。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">class example {</span><br><span class="line"> constructor(text) {</span><br><span class="line"> this.text = text;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">class example2 extends example {</span><br><span class="line"> constructor(text) {</span><br><span class="line"> super(text);</span><br><span class="line"> console.log(this.text)</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">const test = new example2(123);</span><br></pre></td></tr></table></figure><p>比較需要注意的是子類別並沒有自己的this物件,所以如果在super之前使用this就會報錯。</p>]]></content>
<tags>
<tag> React </tag>
<tag> JavaScript </tag>
</tags>
</entry>
<entry>
<title>「React學習之路」Day2.學習基礎ES6(一)</title>
<link href="/2020/01/18/Introduction-and-Practice-React-Day-2/"/>
<url>/2020/01/18/Introduction-and-Practice-React-Day-2/</url>
<content type="html"><![CDATA[<blockquote><p>ECMAScript是一種由Ecma國際(前身為歐洲電腦製造商協會)在標準ECMA-262中定義的手稿語言規範。這種語言在全球資訊網上應用廣泛,它往往被稱為JavaScript或JScript,但實際上後兩者是ECMA-262標準的實現和擴充。 - 維基百科</p></blockquote><h2 id="ES6-新特性"><a class="header-anchor" href="#ES6-新特性"></a>ES6 新特性</h2><p>ES6的目標是使JavaScript可以開發更複雜的大型應用,並成為企業級開發語言。</p><p>ES6中新增了let和const這兩種用來宣告的關鍵字,我們來試試看他們與我們以前常用的var有什麼不同。</p><h3 id="let"><a class="header-anchor" href="#let"></a>let</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">let ttt = 123;</span><br><span class="line">console.log(ttt);</span><br></pre></td></tr></table></figure><p>let跟var的差別是var在宣告時會把自己提升到程式頂端。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">console.log(qqq);</span><br><span class="line">var qqq;</span><br></pre></td></tr></table></figure><p>這樣用var宣告,他不會報錯,但是如果換成let就會報錯。</p><h3 id="const"><a class="header-anchor" href="#const"></a>const</h3><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const test = 'test'</span><br></pre></td></tr></table></figure><p>const比較特殊的是如果是「值」的宣告,那麼他在後面就不能再改變,但是如果是陣列或物件,那麼陣列和物件內的值還是可以做改變,這是因為const的宣告常數是指向該物件或陣列的記憶體位置,只要記憶體位置不變,那麼就不會錯誤。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const test1 = {};</span><br><span class="line">test1.example = 123;</span><br><span class="line">console.log(test1);</span><br><span class="line"></span><br><span class="line">test1 = {}; //error</span><br></pre></td></tr></table></figure><h3 id="展開運算子"><a class="header-anchor" href="#展開運算子"></a>展開運算子</h3><p>不知道各位有沒有看過 「…var1」 這種類型的用法呢?其實這叫 Spread,他的作用就是在陣列或物件前面加上…他會展開陣列或物件內的值</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">const example1 = [1, 2, 3]</span><br><span class="line">const example2 = [...example1, 4, 5]</span><br><span class="line">console.log(example2)</span><br><span class="line">console.log(...example2)</span><br><span class="line"></span><br><span class="line">[Log] [1, 2, 3, 4, 5] (5)</span><br><span class="line">[Log] 1 – 2 – 3 – 4 – 5</span><br></pre></td></tr></table></figure><h3 id="定義函數"><a class="header-anchor" href="#定義函數"></a>定義函數</h3><p>在ES6中,我們可以使用 => 來定義函數,下面來看看ES5和ES6中定義函數的差別。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">//ES5</span><br><span class="line">var example = function (text1, text2) {</span><br><span class="line"> console.log(text1 + text2);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">//ES6</span><br><span class="line">var example = (text1, text2) => {console.log(text1 + text2)}</span><br></pre></td></tr></table></figure><p>同時,大括弧內所指的「this」會使用外面一層的「this」。</p><h3 id="模組匯入與匯出"><a class="header-anchor" href="#模組匯入與匯出"></a>模組匯入與匯出</h3><p>匯出模組</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">export var example = 'test';</span><br><span class="line">export function example2() {console.log('Hello')}</span><br></pre></td></tr></table></figure><p>匯入模組</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">import example3 from example3</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> React </tag>
<tag> JavaScript </tag>
</tags>
</entry>
<entry>
<title>「React學習之路」Day1.從JavaScript出發</title>
<link href="/2020/01/16/Introduction-and-Practice-React-Day-1/"/>
<url>/2020/01/16/Introduction-and-Practice-React-Day-1/</url>
<content type="html"><![CDATA[<p>繼上一章說「<a href="https://blakefunteis.github.io/2019/11/10/%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87ReactJS%EF%BC%9F/">為什麼選擇ReactJS?</a>」已經過了好一段時間了,想想應該繼續這個主題,所以之後的幾天主題都會圍繞在React上。</p><h2 id="從JavaScript出發"><a class="header-anchor" href="#從JavaScript出發"></a>從JavaScript出發</h2><p>在了解React之前,我們必須先了解JavaScript。</p><h3 id="基本介紹"><a class="header-anchor" href="#基本介紹"></a>基本介紹</h3><blockquote><p>JavaScript(通常縮寫為JS)是一種進階的、直譯的程式語言[5]。JavaScript是一門基於原型、函式先行的語言[6],是一門多範式的語言,它支援物件導向編程,指令式程式設計,以及函式語言程式設計。它提供語法來操控文字、陣列、日期以及正規表示式等,不支援I/O,比如網路、儲存和圖形等,但這些都可以由它的宿主環境提供支援。它已經由ECMA(歐洲電腦製造商協會)透過ECMAScript實作語言的標準化[5]。它被世界上的絕大多數網站所使用,也被世界主流瀏覽器(Chrome、IE、Firefox、Safari、Opera)支援。 - 維基百科</p></blockquote><h3 id="變數型態"><a class="header-anchor" href="#變數型態"></a>變數型態</h3><p>在JavaScript中,有兩種宣告方式</p><blockquote><ol><li>顯式宣告:使用var宣告</li><li>隱式宣告:不使用var宣告</li></ol></blockquote><p>隱式宣告就是不用宣告即可直接使用這個變數</p><table><thead><tr><th>型態</th><th>描述</th><th>範例</th></tr></thead><tbody><tr><td>undefined</td><td>沒宣告的變數,或宣告過卻沒初始化的變數</td><td>var test = undefined;</td></tr><tr><td>string</td><td>字串</td><td>var test = ‘test’, test2 = “test”;</td></tr><tr><td>number</td><td>64bits整數</td><td>var test = 123;</td></tr><tr><td>boolean</td><td>布林值</td><td>var test = true, test = false;</td></tr><tr><td>function</td><td>函數</td><td>var test = function(){};</td></tr><tr><td>null</td><td>空</td><td>var test = null;</td></tr><tr><td>object</td><td>物件</td><td>var test = {}, test = {num: 123};</td></tr><tr><td>array</td><td>陣列</td><td>var test = [], test = [1, 2, ,3];</td></tr></tbody></table><h3 id="事件驅動-Event-Driven"><a class="header-anchor" href="#事件驅動-Event-Driven"></a>事件驅動 Event-Driven</h3><p>JavaScript最大的特色就是<strong>事件驅動</strong>的機制,他是以事件為單位在執行事件,第一個事件執行完成,他會找下一個事件,當事件都執行完,那麼程式就結束了,我們來看看最經典的例子。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">console.log(1);</span><br><span class="line"></span><br><span class="line">setTimeout(function(){</span><br><span class="line"> console.log(2);</span><br><span class="line">}, 1000)</span><br><span class="line"></span><br><span class="line">console.log(3);</span><br></pre></td></tr></table></figure><p>執行後結果會是</p><p><img src="1.png" alt></p><p>這邊看到了他印出了1之後印出3然後一秒後又印出2,那麼我們把秒數調整為0看看。</p><p><img src="2.png" alt></p><p>我們秒數設定成0,為什麼執行結果還是一樣呢?<br>因為就如我們一開始所說的JavaScript的事件引擎,<strong>他是以事件為單位在執行事件,第一個事件執行完成,他會找下一個事件,直至事件都執行完畢</strong>。在這邊setTomeOut()並不是只有設定延遲秒數就執行這麼簡單,其實他會向JavaScript的事件引擎註冊一個事件,然後返回並繼續執行下一句程式碼,當每一行程式碼都執行完了,代表當前事件都執行完了,JavaScript會找下一個事件來執行也就是setTimeOut(),所以最後結果才會是我們所看到的這樣。</p><h3 id="原型-Prototype"><a class="header-anchor" href="#原型-Prototype"></a>原型 Prototype</h3><p>在JavaScript中並沒有所謂的類別(Class),所以要使用類似物件導向的Class(類別),我們就需要使用原型來包裝物件。</p><p>我們先建立一個物件</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">var myObject = function(){</span><br><span class="line">this.text = 'Hello';</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">var test = new myObject();</span><br><span class="line">console.log(test.text);</span><br></pre></td></tr></table></figure><p>之後我們開始使用原型</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">myObject.prototype.example = function(){</span><br><span class="line"> this.text = this.text + 'World!';</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">test.example();</span><br><span class="line">console.log(test.text);</span><br></pre></td></tr></table></figure><p>返回了以下結果</p><p><img src="3.png" alt></p><h3 id="記憶體回收機制"><a class="header-anchor" href="#記憶體回收機制"></a>記憶體回收機制</h3><p>跟其他程式語言不同,在JavaScript並沒有直接釋放記憶體空間的方法,而是使用垃圾回收機制(Garbage Collection)簡稱GC。<br>在JavaScript內所有組成都是物件所組成,在每個物件上都有一個計數器,記錄著現在有多少變數使用自己,一但計數器歸0,那麼他很有可能被GC所回收。</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">var test1 = new myObject();</span><br><span class="line">var test2 = test1;</span><br></pre></td></tr></table></figure><p>我們宣告test1這個變數讓他去裝myObject這個物件,然後又使用test2去關聯同一個物件,因此這個時候,物件的計數次數就是2,代表有兩個變數去使用它。</p><p>所以如果我們要讓GC回收上面的物件,那麼就要移除與這個物件有關的變數</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">test1 = null;</span><br><span class="line">test2 = null;</span><br></pre></td></tr></table></figure><p>到這裡物件就被回收了,但是還是有變數,我們如何也移除變數?</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">delete test1;</span><br><span class="line">delete test2;</span><br></pre></td></tr></table></figure><p>這樣就可以移除這個變數了。</p>]]></content>
<tags>
<tag> React </tag>
<tag> JavaScript </tag>
</tags>
</entry>
<entry>
<title>在Mac環境下的MAMP安裝PHP擴展</title>
<link href="/2020/01/15/%E5%9C%A8Mac%E7%92%B0%E5%A2%83%E4%B8%8B%E7%9A%84MAMP%E5%AE%89%E8%A3%9DPHP%E6%93%B4%E5%B1%95/"/>
<url>/2020/01/15/%E5%9C%A8Mac%E7%92%B0%E5%A2%83%E4%B8%8B%E7%9A%84MAMP%E5%AE%89%E8%A3%9DPHP%E6%93%B4%E5%B1%95/</url>
<content type="html"><![CDATA[<p>今天要準備的東西有</p><ul><li>MAMP (PHP 7.3.7)</li><li>Stats 2.0.3</li><li>XCode</li></ul><h2 id="安裝步驟"><a class="header-anchor" href="#安裝步驟"></a>安裝步驟</h2><p>先把stats下載下來並且解壓縮</p><p><img src="1.png" alt></p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ wget https://pecl.php.net/get/stats-2.0.3.tgz</span><br><span class="line">$ tar zxvf stats-2.0.3.tgz</span><br></pre></td></tr></table></figure><p>之後切換到已經解壓縮好的資料夾內</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ cd stats-2.0.3</span><br></pre></td></tr></table></figure><p>這時候要使用phpize</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ /Applications/MAMP/bin/php/php7.3.7/bin/phpize</span><br></pre></td></tr></table></figure><p>之後使用MAMP內的php7.3.7的php-config執行configure<br>然後直接執行 make && make install 就可以編譯完成</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ ./configure --with-php-config=/Applications/MAMP/bin/php/php7.3.7/bin/php-config</span><br><span class="line">$ make && make install</span><br></pre></td></tr></table></figure><p>之後直接在php.ini內增加</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">extension=stats.so</span><br></pre></td></tr></table></figure><p>然後重啟MAMP內的Apache就可以囉</p><p><img src="2.jpg" alt></p><p>其實大部分PHP的擴展安裝方法,都是差不多這樣的。所以以後如果有其他擴展需要安裝,不妨參考看看這些步驟。</p><h2 id="如果你遇到了以下問題"><a class="header-anchor" href="#如果你遇到了以下問題"></a>如果你遇到了以下問題</h2><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">xcrun: error: invalid active developer path (/Library/Developer/CommandLineTools), missing xcrun at: /Library/Developer/CommandLineTools/usr/bin/xcrun</span><br></pre></td></tr></table></figure><p>請執行以下指令</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">$ xcode-select --install</span><br></pre></td></tr></table></figure>]]></content>
<tags>
<tag> PHP </tag>
</tags>
</entry>
<entry>
<title>用一個領取折價券來舉例時常出現的邏輯錯誤</title>
<link href="/2020/01/14/%E7%94%A8%E4%B8%80%E5%80%8B%E9%A0%98%E5%8F%96%E6%8A%98%E5%83%B9%E5%88%B8%E4%BE%86%E8%88%89%E4%BE%8B%E6%99%82%E5%B8%B8%E5%87%BA%E7%8F%BE%E7%9A%84%E9%82%8F%E8%BC%AF%E9%8C%AF%E8%AA%A4/"/>
<url>/2020/01/14/%E7%94%A8%E4%B8%80%E5%80%8B%E9%A0%98%E5%8F%96%E6%8A%98%E5%83%B9%E5%88%B8%E4%BE%86%E8%88%89%E4%BE%8B%E6%99%82%E5%B8%B8%E5%87%BA%E7%8F%BE%E7%9A%84%E9%82%8F%E8%BC%AF%E9%8C%AF%E8%AA%A4/</url>
<content type="html"><![CDATA[<p>在我們寫專案的過程中,時常碰到需要先判斷是否已經有這筆資料了,沒有的話就寫入,有的話就彈出錯誤。下面我們來用領取折價券來模擬這個狀況。</p><p>我們先構建出一個基本的領取折價券的資料表結構</p><table><thead><tr><th>名稱</th><th>類型</th><th>註解</th></tr></thead><tbody><tr><td>id</td><td>int</td><td>PK</td></tr><tr><td>user_id</td><td>int</td><td>用戶ID</td></tr><tr><td>amount_id</td><td>int</td><td>價格ID</td></tr><tr><td>serial_number</td><td>char</td><td>折價券序號</td></tr></tbody></table><pre><code>CREATE TABLE `test`.`test` ( `id` int(10) NOT NULL AUTO_INCREMENT, `user_id` int(10) NOT NULL, `amount_id` int(10) NOT NULL, `serial_number` char(32) NOT NULL, `created_at` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0), `updated_at` datetime(0) NOT NULL DEFAULT CURRENT_TIMESTAMP(0) ON UPDATE CURRENT_TIMESTAMP(0), PRIMARY KEY (`id`));</code></pre><p>這時候有一個需求,一個用戶只能領取五次折價券,這時候我們一般思考步驟是</p><ol><li>先判斷這個用戶有沒有領取超過五次</li><li>沒有則寫入並返回成功,有則不寫入並返回失敗。</li></ol><p>之後我們按照這邏輯開始寫程式碼。(這邊使用PHP來舉例)</p><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line"><?php</span><br><span class="line">$DBNAME = "test";</span><br><span class="line">$DBUSER = "root";</span><br><span class="line">$DBPASSWD = "root";</span><br><span class="line">$DBHOST = "localhost";</span><br><span class="line">$userId = 1;</span><br><span class="line">$conn = mysqli_connect($DBHOST, $DBUSER, $DBPASSWD);</span><br><span class="line">if (empty($conn)) {</span><br><span class="line"> print mysqli_error($conn);</span><br><span class="line"> die ("無法連結資料庫");</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">if (!mysqli_select_db($conn, $DBNAME)) {</span><br><span class="line"> die ("無法選擇資料庫");</span><br><span class="line">}</span><br><span class="line">// 設定連線編碼</span><br><span class="line">mysqli_query($conn, "SET NAMES 'utf8'");</span><br><span class="line">$sql = "select count(*) from `test` where user_id=" . $userId;</span><br><span class="line">$count = mysqli_query($conn, $sql);</span><br><span class="line">$count = mysqli_fetch_array($count);</span><br><span class="line">if ($count[0] >= 5) {</span><br><span class="line"> die ("折價券領取的次數超過五次");</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$sql = "INSERT INTO `test`.`test`(`user_id`, `amount_id`, `serial_number`) VALUES ($userId, 1, '11111111111111111111111111111111');";</span><br><span class="line">$result = mysqli_query($conn, $sql);</span><br><span class="line">if ($result) {</span><br><span class="line"> echo '領取成功';</span><br><span class="line"> exit;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">echo '領取失敗';</span><br><span class="line">exit;</span><br></pre></td></tr></table></figure><p>到這邊,邏輯就寫完了,我們寫一個ajax來試著敲敲看,看看會發生什麼事情。</p><p><img src="1.png" alt></p><p><img src="2.png" alt></p><p>資料庫內顯示有六筆,為什麼會這樣?</p><p>因為我們先判斷後寫入的這個流程所導致,當請求幾乎是併發過來的時候,會先通過判斷是否超過五個,這時候我們資料尚未寫入,所以這邊會是成功的,但是就是因為成功,所以可能導致五個之後的請求也會通過這個判斷。</p><p>那我們怎麼做可以避免這個情況呢?</p><ol><li><strong>可以試著修改資料庫語句</strong></li></ol><figure class="highlight plain"><table><tr><td class="code"><pre><span class="line">INSERT INTO test ( user_id, amount_id, serial_number )</span><br><span class="line">SELECT '1', '112', '1123123' FROM (SELECT count(user_id) as count FROM test WHERE user_id = 1) as temp where temp.count < 5</span><br></pre></td></tr></table></figure><p>把兩句判斷合併再一起就可以避免這個情況</p><ol start="2"><li>使用UNIQUE,不過因為我們這次的需求是可以領取五張,五張以上才不能領,所以這方法在這需求下無法使用</li></ol>]]></content>
<tags>
<tag> Code </tag>
</tags>
</entry>
<entry>
<title>一句更新在MySQL底層是如何運作的?</title>
<link href="/2020/01/07/how-run-a-update-in-mysql/"/>
<url>/2020/01/07/how-run-a-update-in-mysql/</url>
<content type="html"><![CDATA[<p>繼上一章「<a href="https://blakefunteis.github.io/2020/01/05/how-run-a-select-in-mysql">一句查詢在MySQL底層是如何運作的?</a>」我們了解了MySQL在一句SQL查詢語句後,如何分析優化和執行該語句。</p><pre><code>客戶端 → 連接器 → 分析器 → 優化器 → 執行器 ↘ ↙ 查詢緩存</code></pre><p>其實更新語句,同樣也會走這個流程。不過他少了查詢緩存,確切來說他不是少了查詢緩存,而是清除緩存,就如上一章我們所講,如果表有變更,他就會清除該表內的查詢緩存,所以才不建議使用查詢緩存,同時他跟查詢還有幾點不同,這個我們稍後會講到。</p><p>過去的時候,不管是工作還是在學進修的機會,我們有非常低的機率會遇到資料庫整個資料異常,需要恢復到一個禮拜前的資料,但是那時候沒有執行資料備份出成為sql檔案,那麼我們要如何把資料庫還原到一個禮拜前的狀態?</p><p>這時候就要說更新語句跟查詢語句不一樣的地方了,同時也是今天這主題的兩個主角,就是「<a href="https://en.wikipedia.org/wiki/Redo_log" target="_blank" rel="noopener">Redo Log 重做日誌</a>」和「<a href="https://baike.baidu.com/item/Mysql%20Binlog#1" target="_blank" rel="noopener">Binlog 歸檔日誌</a>」</p><h3 id="Redo-Log-重做日誌"><a class="header-anchor" href="#Redo-Log-重做日誌"></a>Redo Log 重做日誌</h3><p><img src="1.jpg" alt></p><p>我們平常在外面消費會有記帳的習慣,在還沒有記帳APP的時候,都是先記錄在紙上,但是因為每天都會消費,所以帳越來越多,我們一定還會有一本記帳小本本,來專門記錄所有的帳。如果今天要記帳,那麼我可以有兩種做法</p><ol><li>直接拿出記帳小本本,紀錄這筆帳</li><li>先記錄在紙上,等回家之後再記錄到記帳小本本上。</li></ol><p>在外面很忙或者不好拿出記帳本的時候,我們肯定都是選擇二者,先記錄在紙上,等回家之後再紀錄到記帳本上,因為前者我們必須拿著一本比較重的記帳本,然後還要翻到那一頁的日期再進行紀錄。速度和方便性自然都是第二者比較快比較方便。</p><p>同樣的在MySQL也是有相同的問題,如果每次資料都是寫入硬碟(記帳小本本),然後硬碟(記帳小本本)還要找到相應的資料,之後硬碟(記帳小本本)在進行更新,整個IO成本都太高,為了解決這個問題,MySQL的作者也採用了類似上面的方式來解決這問題。</p><p>記帳紙和記帳本之間的關係,其實就是MySQL中的 <strong>Write-Ahead Logging</strong> 先寫日誌再寫硬碟,也就是先寫記帳紙,等回家之後或者能抽空的時候在寫記帳本。</p><p>當有一條資料要更新的時候,<strong>InnoDB</strong> 會先把紀錄寫進Redo Log(記帳紙)上,並且更新記憶體,到這邊更新其實就算完成了。同時,InnoDB會在適當的時候將這筆更新寫進硬碟,但是這個通常都是資料庫比較空閑的時候才會做的,就像我們回家才會把記帳紙內的帳目紀錄到記帳本上。</p><p>Redo Log也是有固定的大小,就像我們的記帳紙一樣,都會有寫滿的一天,那麼當Redo Log被寫滿了,就必須先把部分寫進硬碟,才能為之後新的紀錄騰出空間。這樣即使資料庫發生異常重啟,之前提交的紀錄也不會消失,這個也稱之為「Crash-Safe」。</p><h3 id="Binlog-歸檔日誌"><a class="header-anchor" href="#Binlog-歸檔日誌"></a>Binlog 歸檔日誌</h3><p>Redo Log 是InnoDB引擎的特有日誌,而Server本身當然也有自己的日誌就是Binlog。</p><p>為什麼會有兩份日誌呢?<br>因為一開始MySQL並沒有InnoDB的引擎,MySQL自帶的是MyISAM,但是MyISAM沒有Crash-Safe的能力,Binlog又只能用於歸檔。而InnoDB是另一個公司以插件的形式導入MySQL的。既然依靠Binlog無法實現Crash-Safe,那麼InnoDB只好使用另一套日誌Redo Log來實現Crash-Safe,這就是為什麼有兩套日誌的原因。</p><h4 id="Redo-Log和Binlog的差異"><a class="header-anchor" href="#Redo-Log和Binlog的差異"></a>Redo Log和Binlog的差異</h4><ol><li>Redo log是InnoDB獨有,而Binlog是MySQL內建的。</li><li>Redo log紀錄的是“做了什麼修改”;Binlog則是“某ID=10的欄位A改成100”</li><li>Redo log是循環寫的,空間會用完,如果要再新增,那麼就要把之前的一些紀錄清除掉;Binlog寫到一定大小後會切換到下一個,並不會覆蓋之前所寫的</li></ol><p>了解兩個日誌,我們來看看InnoDB在Update語句時候的流程是什麼</p><ol><li>執行器先找InnoDB取出例如ID等於10的,因ID是主鍵,所以會用樹搜索到這一筆資料,如果資料本來就在記憶體中就直接返回給執行器,如果沒有,則從硬碟中取出在寫進記憶體並且返回。</li><li>執行器拿到資料後把資料變更為Update所要更改的資料成為新資料,之後直接調用InnoDB寫入新資料。</li><li>InnoDB將這筆資料寫入記憶體中,同時也會將這筆操作寫入Redo log中。</li><li>執行器產生這筆操作的binlog,並且把binlog寫入硬碟。</li><li>執行器調用InnoDB的提交接口,InnoDB把剛剛寫入的Redo log改成提交的狀態。</li></ol><p>到此一句簡單的更新完成。</p>]]></content>
<tags>
<tag> MySQL </tag>
</tags>
</entry>
<entry>
<title>一句查詢在MySQL底層是如何運作的?</title>
<link href="/2020/01/05/how-run-a-select-in-mysql/"/>
<url>/2020/01/05/how-run-a-select-in-mysql/</url>
<content type="html"><![CDATA[<p>平常我們使用MySQL都是進行查詢然後資料庫返回結果</p><pre><code>mysql > SELECT * FROM table WHERE id = 1</code></pre><p>但是我們卻不知道這句查詢語句在MySQL內部的執行過程,所以我們一起來看看MySQL底層對查詢到底做了些什麼事情,這樣當我們碰到一些異常或者問題時,就可以直指本質,更快速的找出問題發生點並解決。</p><pre><code>客戶端 → 連接器 → 分析器 → 優化器 → 執行器 ↘ ↙ 查詢緩存</code></pre><h3 id="連接器"><a class="header-anchor" href="#連接器"></a>連接器</h3><p>負責建立維持和管理連線、獲取權限。</p><pre><code>mysql -u root -p</code></pre><p>一般來說command line連線的指令會是上述這句,在完成TCP握手之後,連接器會開始驗證你的身份,這時候用的就是你的帳號和密碼。</p><ol><li>如果帳號或者密碼錯誤,你會收到 ”Access denied for user” 的錯誤,然後客戶端(海豚, phpmyadmin, cli, etc….)會結束此條連線請求</li><li>如果帳號密碼皆正確,連接器會到權限資料表查出你擁有的權限,之後這個連接的權限判斷邏輯,都會依賴此時讀到的權限。</li></ol><p>在這邊解釋了,為什麼我們每次修改權限,都需要再次新建連線,才會讀到新的權限配置。</p><p>連接完成後,如果沒有執行任何動作,這條連線就會處於Sleep狀態</p><p><img src="1.png" alt></p><p>那條Sleep連線是我剛剛建立的新連線,各位如果想實際操作,可以建立新連線後,在舊有的連線中使用這句指令</p><pre><code>mysql > show processlist #查看mysql目前的用戶連線進程</code></pre><p>如果連線太長時間沒有操作,連接器就會自動斷開連線,預設是8小時,如果需要修改可以變更 <strong>wait_tomeout</strong>。</p><p>連接被斷開之後,客戶端再次發送請求的話,就會收到 “Lost connection to MySQL server during query”的錯誤,這時候如果要繼續,就必須要重新建立新連線,然後再執行請求。</p><p>建立連線過程,通常都是比較複雜的,所以建議盡量減少使用建立連線的動作,也就是說盡量使用長連線,但是全部使用長連線的話,有可能會導致MySQL佔用記憶體上漲很快,這是因為MySQL在執行過程中臨時使用的記憶體是管理在連線對象裡面的,這些資源如果沒做其他動作,那麼只有在斷開連線的時候才會釋放,所以如果長時間累積下來,可能會導致記憶體佔用過大,被系統強行kill。</p><p>如何解決這個問題?</p><ol><li>在完成一個佔用大量內存的大查詢後,斷開連線,之後再重建連線。</li><li>可以使用 mysql_reset_connection 不過這個指令只支持MySQL5.7包含以上的版本,來重新初始化連線,他會將連線恢復到剛創建完的狀態。</li></ol><h3 id="查詢緩存"><a class="header-anchor" href="#查詢緩存"></a>查詢緩存</h3><p>連線完成後,就可以使用SELECT語句,這時候會來到第二步,查詢緩存。</p><p>MySQL得到一句SELECT後,會先到緩存搜尋看看之前是不是有執行過這條查詢,之前執行的語句會以key-value的形式緩存在記憶體中。key是查詢的語句,value則是結果,如果有匹配的緩存,就會直接返回value。如果緩存中沒有,MySQL會進行查詢後,將查詢結果寫進緩存當中。如果使用了查詢緩存返回資料,那麼資料庫就不需要執行後面複雜的操作,直接可以返回結果,這樣可以大大提高這個查詢在資料庫的效率。</p><p>但是大多數的情況下,建議不要使用緩存。為什麼呢?</p><ol><li>在一個頻繁會更改的表,在更新的時候該表內所有的緩存都將全部被清空,因此很有可能在未使用到緩存的時候,該表的緩存已經被全部清空了。除非是使用長期不會變動的表,否則不太建議使用查詢緩存。</li><li>MySQL 8.0 已經把緩存功能徹底拔除。</li></ol><h3 id="分析器"><a class="header-anchor" href="#分析器"></a>分析器</h3><p>如果緩存沒有查到你要的結果,那麼就會開始真正執行搜尋語句,首先,MySQL會需要分析你的查詢語句的意思。</p><p>MySQL會抓取關鍵字,以我們一開始的那句為例,SELECT判斷出這是一個搜尋語句,table判斷為表名,id判斷為欄位名。同時也會判斷你這句查詢是否符合MySQL的查詢語法規則。</p><p>如果判斷輸入的MySQL查詢語句是錯的,那麼他就會返回錯誤給客戶端</p><pre><code>1064 - You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'how processlist # 123123123' at line 1, Time: 0.003000s</code></pre><p>一般的語法錯誤會出現在 <strong>use near</strong> 後面</p><h3 id="優化器"><a class="header-anchor" href="#優化器"></a>優化器</h3><p>經過了分析器,MySQL已經知道你想做什麼,在開始執行前也需要經過優化器處理。</p><p>優化器主要的工作是當表裡有多個索引,決定使用哪個索引,或者在一個查詢語法裡面有Join的時候,決定各個表的連接順序。優化器工作完成之後,這句的執行流程方式,基本上就已經定型了。</p><h3 id="執行器"><a class="header-anchor" href="#執行器"></a>執行器</h3><p>MySQL透過分析器知道你要做什麼,通過優化器知道該如何做,接下來就是要執行查詢語句了。</p><p>開始執行時,會先判斷你是否有對這個表搜尋的權限,如果有查詢緩存,會在緩存返回時,進行權限判斷。如果沒有權限則會返回以下訊息</p><pre><code>mysql > SELECT command denied to user 'test'@'localhost' for table 'table'</code></pre><p>如果有權限就會打開表繼續執行,打開表的時候,執行器會根據表的引擎去選擇該引擎的接口。</p><p>執行流程</p><ol><li>調用引擎取這個表的第一行,判斷ID是否為1,如果不是則跳過,如果是則將這筆結果保存在結果集內。</li><li>調用引擎取下一筆資料,重複驗證判斷,直至取到這個表的最後一行</li><li>執行器將所有滿足條件的結果返回給客戶端</li></ol><p>到此,這個查詢就已經完成了。</p>]]></content>
<tags>
<tag> MySQL </tag>
</tags>
</entry>
<entry>
<title>7-Reverse-Integer</title>
<link href="/2019/11/13/7-Reverse-Integer/"/>
<url>/2019/11/13/7-Reverse-Integer/</url>
<content type="html"><![CDATA[<p>Given a 32-bit signed integer, reverse digits of an integer.</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.</p><pre><code>Input: 123Output: 321Input: -123Output: -321Input: 120Output: 21</code></pre><h2 id="Code"><a class="header-anchor" href="#Code"></a>Code</h2><pre><code>class Solution {/*** @param Integer $x* @return Integer*/function reverse($x) {if ($x < 0) {$x = '-'.substr(strrev($x), 0, -1);} else {$x = strrev($x);}return $x > 2147483647 || $x < -2147483647? 0: (int)$x;}}</code></pre><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/reverse-integer" title="7. Reverse Integer" target="_blank" rel="noopener">7. Reverse Integer</a><br><a href="https://github.com/BlakeFunTeis/leetcode-php/blob/master/7-Reverse-Integer.php" title="GitHub" target="_blank" rel="noopener">GitHub</a></p>]]></content>
<tags>
<tag> PHP </tag>
<tag> LeetCode </tag>
</tags>
</entry>
<entry>
<title>為什麼選擇ReactJS?</title>
<link href="/2019/11/10/%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87ReactJS%EF%BC%9F/"/>
<url>/2019/11/10/%E7%82%BA%E4%BB%80%E9%BA%BC%E9%81%B8%E6%93%87ReactJS%EF%BC%9F/</url>
<content type="html"><![CDATA[<h2 id="React-特色"><a class="header-anchor" href="#React-特色"></a>React 特色</h2><blockquote><p>React(有時叫React.js或ReactJS)是一個為資料提供彩現為HTML視圖的開源JavaScript 庫。React視圖通常採用包含以自訂HTML標記規定的其他組件的組件彩現。React為程式設計師提供了一種子組件不能直接影響外層組件(“data flows down”)的模型,資料改變時對HTML文件的有效更新,和現代單頁應用中組件之間乾淨的分離。 - 維基百科</p></blockquote><p>Facebook 在2013年推出的一種開源前端框架。為了解決前端不斷複雜化,導致的效能瓶頸和維護成本。</p><p>優點:</p><ol><li>元件化,使程式更易於維護</li><li>執行效能高</li><li>單向數據流</li><li>同構</li><li>兼容性強</li><li>跨平台性</li></ol><h2 id="虛擬DOM(Virtual-DOM)"><a class="header-anchor" href="#虛擬DOM(Virtual-DOM)"></a>虛擬DOM(Virtual DOM)</h2><p>React核心思想是從元件出發,他會先在程式端放入一段對應到真實DOM的物件,用來管理所有的資料與邏輯,當元件因為資料而更新的時候,React會重新製作一個新的虛擬DOM樹,然後快速地跟舊的虛擬DOM進行比對,之後將有更新的部分更新到真實DOM上。</p><h2 id="元件"><a class="header-anchor" href="#元件"></a>元件</h2><p>虛擬DOM的寫法帶來了有別於以往HTML, CSS的開發習慣,全部寫在一起,而是透過物件導向的方式,讓每個開發者可以專心地針對每個元件撰寫功能和邏輯。</p><h2 id="單向資料流"><a class="header-anchor" href="#單向資料流"></a>單向資料流</h2><p>因為React樹狀化元件的關係,元件和元件之間緊密相連,父元件僅能通過props的方式傳遞至子元件,子元件則沒辦法去修改props裡面的資料。<br>所以通常需要搭配<a href="https://github.com/facebook/flux" target="_blank" rel="noopener">Flux</a>或者<a href="https://github.com/reduxjs/redux" target="_blank" rel="noopener">Redux</a>。</p>]]></content>
<tags>
<tag> React </tag>
</tags>
</entry>
<entry>
<title>182-Duplicate-Emails</title>
<link href="/2019/07/21/182-Duplicate-Emails/"/>
<url>/2019/07/21/182-Duplicate-Emails/</url>
<content type="html"><![CDATA[<h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>Write a SQL query to find all duplicate emails in a table named Person.</p><pre>+----+---------+| Id | Email |+----+---------+| 1 | a@b.com || 2 | c@d.com || 3 | a@b.com |+----+---------+</pre><p>For example, your query should return the following for the above table:</p><pre>+---------+| Email |+---------+| a@b.com |+---------+</pre><h2 id="SQL-Schema"><a class="header-anchor" href="#SQL-Schema"></a>SQL Schema</h2><pre>Create table If Not Exists Person (Id int, Email varchar(255))Truncate table Personinsert into Person (Id, Email) values ('1', 'a@b.com')insert into Person (Id, Email) values ('2', 'c@d.com')insert into Person (Id, Email) values ('3', 'a@b.com')</pre><h2 id="Query"><a class="header-anchor" href="#Query"></a>Query</h2><pre>SELECT Email FROM PersonGroup by EmailHAVING count(Email) > 1</pre><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/duplicate-emails" title="182. Duplicate Emails" target="_blank" rel="noopener">182. Duplicate Emails</a></p>]]></content>
<tags>
<tag> LeetCode </tag>
<tag> MySQL </tag>
<tag> Database </tag>
</tags>
</entry>
<entry>
<title>620-Not-Boring-Movies</title>
<link href="/2019/07/21/620-Not-Boring-Movies/"/>
<url>/2019/07/21/620-Not-Boring-Movies/</url>
<content type="html"><![CDATA[<p>X city opened a new cinema, many people would like to go to this cinema. The cinema also gives out a poster indicating the movies’ ratings and descriptions.</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>Please write a SQL query to output movies with an odd numbered ID and a description that is not ‘boring’. Order the result by rating.</p><h2 id="SQL-Schema"><a class="header-anchor" href="#SQL-Schema"></a>SQL Schema</h2><pre><code>Create table If Not Exists cinema (id int, movie varchar(255), description varchar(255), rating float(2, 1))Truncate table cinemainsert into cinema (id, movie, description, rating) values ('1', 'War', 'great 3D', '8.9')insert into cinema (id, movie, description, rating) values ('2', 'Science', 'fiction', '8.5')insert into cinema (id, movie, description, rating) values ('3', 'irish', 'boring', '6.2')insert into cinema (id, movie, description, rating) values ('4', 'Ice song', 'Fantacy', '8.6')insert into cinema (id, movie, description, rating) values ('5', 'House card', 'Interesting', '9.1')</code></pre><p>For example, table cinema:</p><pre>+---------+-----------+--------------+-----------+| id | movie | description | rating |+---------+-----------+--------------+-----------+| 1 | War | great 3D | 8.9 || 2 | Science | fiction | 8.5 || 3 | irish | boring | 6.2 || 4 | Ice song | Fantacy | 8.6 || 5 | House card| Interesting| 9.1 |+---------+-----------+--------------+-----------+</pre><p>For the example above, the output should be:</p><pre>+---------+-----------+--------------+-----------+| id | movie | description | rating |+---------+-----------+--------------+-----------+| 5 | House card| Interesting| 9.1 || 1 | War | great 3D | 8.9 |+---------+-----------+--------------+-----------+</pre><h2 id="Query"><a class="header-anchor" href="#Query"></a>Query</h2><pre><code># Write your MySQL query statement belowSELECT id, movie, description, rating FROM cinemaWHERE description != 'boring'AND (id % 2) = 1order by rating DESC</code></pre><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/not-boring-movies" title="620. Not Boring Movies" target="_blank" rel="noopener">620. Not Boring Movies</a></p>]]></content>
<tags>
<tag> LeetCode </tag>
<tag> MySQL </tag>
<tag> Database </tag>
</tags>
</entry>
<entry>
<title>1108-Defanging-an-IP-Address</title>
<link href="/2019/07/20/1108-Defanging-an-IP-Address/"/>
<url>/2019/07/20/1108-Defanging-an-IP-Address/</url>
<content type="html"><![CDATA[<p>Given a valid (IPv4) IP <code>address</code>, return a defanged version of that IP address.</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>A defanged IP address replaces every period <code>"."</code> with <code>"[.]"</code>.</p><pre><code>Input: address = "1.1.1.1"Output: "1[.]1[.]1[.]1"Input: address = "255.100.50.0"Output: "255[.]100[.]50[.]0"</code></pre><h2 id="Code"><a class="header-anchor" href="#Code"></a>Code</h2><pre><code>class Solution {/*** @param String $address* @return String*/function defangIPaddr($address) {$address = explode(".", $address);return $address[0] . '[.]' . $address[1] . '[.]' . $address[2] . '[.]' . $address[3];}}</code></pre><p>複雜度為 O(1)。</p><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/defanging-an-ip-address" title="1108. Defanging an IP Address" target="_blank" rel="noopener">1108. Defanging an IP Address</a><br><a href="https://github.com/BlakeFunTeis/leetcode-php/blob/master/1108-Defanging_an_IP_Address.php" title="GitHub" target="_blank" rel="noopener">GitHub</a></p>]]></content>
<tags>
<tag> PHP </tag>
<tag> LeetCode </tag>
</tags>
</entry>
<entry>
<title>595-Big-Countries</title>
<link href="/2019/07/20/595-Big-Countries/"/>
<url>/2019/07/20/595-Big-Countries/</url>
<content type="html"><![CDATA[<p>Write a SQL solution to output big countries’ name, population and area.</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>A country is big if it has an area of bigger than 3 million square km or a population of more than 25 million.</p><pre><code>+--------------+-------------+--------------+| name | population | area |+--------------+-------------+--------------+| Afghanistan | 25500100 | 652230 || Algeria | 37100000 | 2381741 |+--------------+-------------+--------------+</code></pre><h2 id="SQL-Schema"><a class="header-anchor" href="#SQL-Schema"></a>SQL Schema</h2><pre><code>Create table If Not Exists World (name varchar(255), continent varchar(255), area int, population int, gdp int)Truncate table Worldinsert into World (name, continent, area, population, gdp) values ('Afghanistan', 'Asia', '652230', '25500100', '20343000000')insert into World (name, continent, area, population, gdp) values ('Albania', 'Europe', '28748', '2831741', '12960000000')insert into World (name, continent, area, population, gdp) values ('Algeria', 'Africa', '2381741', '37100000', '188681000000')insert into World (name, continent, area, population, gdp) values ('Andorra', 'Europe', '468', '78115', '3712000000')insert into World (name, continent, area, population, gdp) values ('Angola', 'Africa', '1246700', '20609294', '100990000000')</code></pre><h2 id="Query"><a class="header-anchor" href="#Query"></a>Query</h2><pre><code># Write your MySQL query statement belowSELECT name, population, area FROM WorldWHERE population > 25000000OR area > 3000000</code></pre><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/big-countries" title="595. Big Countries" target="_blank" rel="noopener">595. Big Countries</a></p>]]></content>
<tags>
<tag> LeetCode </tag>
<tag> MySQL </tag>
<tag> Database </tag>
</tags>
</entry>
<entry>
<title>771-Jewels and Stones</title>
<link href="/2019/07/20/771-Jewels-and-Stones/"/>
<url>/2019/07/20/771-Jewels-and-Stones/</url>
<content type="html"><![CDATA[<p>You’re given strings J representing the types of stones that are jewels, and S representing the stones you have. Each character in S is a type of stone you have. You want to know how many of the stones you have are also jewels.</p><p>The letters in J are guaranteed distinct, and all characters in J and S are letters. Letters are case sensitive, so “a” is considered a different type of stone from “A”.</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><pre><code>Input: J = "aA", S = "aAAbbbb"Output: 3Input: J = "z", S = "ZZ"Output: 0</code></pre><h2 id="Note"><a class="header-anchor" href="#Note"></a>Note</h2><p><code>S</code> and <code>J</code> will consist of letters and have length at most 50.<br>The characters in <code>J</code> are distinct.</p><h2 id="Code"><a class="header-anchor" href="#Code"></a>Code</h2><pre><code>class Solution {/*** @param String $J* @param String $S* @return Integer*/function numJewelsInStones($J, $S) {$count = 0;$S = str_split($S);$data = array_count_values($S);for($i=0; $i<=strlen($J); $i++) {$count += $data[$J[$i]];}return $count;}}</code></pre><p>複雜度為 <strong>O(n)</strong>。</p><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://leetcode.com/problems/jewels-and-stones" title="771. Jewels and Stones" target="_blank" rel="noopener">771. Jewels and Stones</a><br><a href="https://github.com/BlakeFunTeis/leetcode-php/blob/master/771-Jewels_and_Stones.php" title="GitHub" target="_blank" rel="noopener">GitHub</a></p>]]></content>
<tags>
<tag> PHP </tag>
<tag> LeetCode </tag>
</tags>
</entry>
<entry>
<title>使用PHP模擬蒙提霍爾問題</title>
<link href="/2019/07/18/%E4%BD%BF%E7%94%A8PHP%E6%A8%A1%E6%93%AC%E8%92%99%E6%8F%90%E9%9C%8D%E7%88%BE%E5%95%8F%E9%A1%8C/"/>
<url>/2019/07/18/%E4%BD%BF%E7%94%A8PHP%E6%A8%A1%E6%93%AC%E8%92%99%E6%8F%90%E9%9C%8D%E7%88%BE%E5%95%8F%E9%A1%8C/</url>
<content type="html"><![CDATA[<p><strong>蒙提霍爾問題</strong>,亦稱為<strong>蒙特霍問題</strong>或<strong>三門問題</strong>(英文:Monty Hall problem),是一個源自博弈論的數學遊戲問題。<br>問題的名字來自該節目的主持人<a href="https://zh.wikipedia.org/wiki/%E8%92%99%E8%92%82%C2%B7%E9%9C%8D%E5%B0%94" title="蒙蒂·霍爾" target="_blank" rel="noopener">蒙蒂·霍爾</a>。</p><h2 id="Rules"><a class="header-anchor" href="#Rules"></a>Rules</h2><p>這個遊戲的玩法是:參賽者會看見三扇關閉了的門,其中一扇的後面有一輛汽車或者是獎品,選中後面有車的那扇門就可以贏得該汽車或獎品,而另外兩扇門後面則各藏有一隻山羊。</p><p>當參賽者選定了一扇門,但未去開啟它的時候,知道門後情形的節目主持人會開啟剩下兩扇門的其中一扇,露出其中一隻山羊。主持人其後會問參賽者要不要換另一扇仍然關上的門。</p><p>問題是:換另一扇門會否增加參賽者贏得汽車的機率?如果嚴格按照上述的條件的話,答案是<strong>會</strong>。換門的話,贏得汽車的機率是2/3。</p><h2 id="Code"><a class="header-anchor" href="#Code"></a>Code</h2><p>建立一個類別 <strong>ThreeDoor</strong>,宣告玩家數 <strong>10000</strong>,並且實作Function <strong>run</strong>。</p><pre><code>class ThreeDoor{private $max_player = 100000;public function run{//TODO: 實作模擬蒙提霍爾問題}}</code></pre><p>宣告成功與失敗的變數</p><pre><code>public function run{$yes = 0;$no = 0;}</code></pre><p>執行迴圈,讓玩家選擇三門中的一門。<br><br>依照遊戲規則,如果玩家選擇的是汽車,那麼主持人就隨意開啟一扇門給他,如果玩家開啟的不是汽車則主持人<strong>必須開啟另外一扇不是汽車的門</strong>給他。</p><pre><code>// 答案$answer = rand(1, 3);// 選擇$choice = rand(1, 3);// 排除選擇後的選擇$other = [1, 2, 3];unset($other[$choice - 1]);// 如果 選擇等於答案 那麼就任意開一扇門給他if ($choice === $answer) {$point = array_rand($other) + 1;} else { //否則 就排除答案的門 開另一扇門給他$temp = $other;unset($temp[$answer - 1]);$temp = array_values($temp);$point = $temp[0];}</code></pre><p>開始計算玩家換門的話的成功與失敗機率</p><pre><code>// 取得剩餘的那道門,玩家換的話的門$temp = $other;unset($temp[$point - 1]);$temp = array_values($temp);$player_change2 = $temp[0];if ($answer === $player_change2) {$yes += 1;} elseif ($answer === $choice) {$no += 1;}echo "換的話,中獎的機率:" . $yes / $this->max_player . "<br>";echo "不換的話,中獎的機率:" . $no / $this->max_player . "<br>";</code></pre><h2 id="Conclusion"><a class="header-anchor" href="#Conclusion"></a>Conclusion</h2><p>程式執行結果</p><pre><code>換的話,中獎的機率:0.66475不換的話,中獎的機率:0.33525</code></pre><h2 id="Reference"><a class="header-anchor" href="#Reference"></a>Reference</h2><p><a href="https://github.com/BlakeFunTeis/ThreeDoor-PHP/" title="使用PHP模擬蒙提霍爾問題(GitHub" target="_blank" rel="noopener">使用PHP模擬蒙提霍爾問題(GitHub)</a><br><a href="https://zh.wikipedia.org/wiki/%E8%92%99%E6%8F%90%E9%9C%8D%E7%88%BE%E5%95%8F%E9%A1%8C" title="蒙提霍爾問題" target="_blank" rel="noopener">蒙提霍爾問題</a></p>]]></content>
<tags>
<tag> PHP </tag>
</tags>
</entry>
</search>