初學者入門學習的演算法 - 合併排序法 Merge Sort 理解歸併排序背後的邏輯 Reference 初學者入門學習的演算法 - 合併排序法 Merge Sort 排序是指按特定順序(數字或字母順序)排列列表中的項目。排序通常與搜索一起使用。 如果在視覺上和算法上對列表進行了排序,那麼在給定列表中搜索元素(稱為key值)通常會更容易。 有很多方法(算法)可以對給定的元素列表進行排序。歸併排序是一種更流行、更有效的方法。
理解歸併排序背後的邏輯 合併排序使用分而治之的概念對給定的元素列表進行排序。它將問題分解為更小的子問題,直到它們變得簡單到可以直接解決。
以下是歸併排序的步驟:
將給定的列表分成兩半(對於具有奇數個元素的列表,大致相等的一半)。 繼續以相同的方式劃分子數組,直到只剩下單個元素數組。 從單元素數組開始,合併子數組,以便對每個合併的子數組進行排序。 重複第 3 步,最終得到一個排序數組。
function merge(left, right) {
let arr = []
// Break out of loop if any one of the array gets empty
while (left.length && right.length) {
// Pick the smaller among the smallest element of left and right sub arrays
if (left[0] < right[0]) {
arr.push(left.shift())
} else {
arr.push(right.shift())
}
}
// Concatenating the leftover elements
// (in case we didn't go through the entire left or right array)
return [ ...arr, ...left, ...right ]
}
function mergeSort(array) {
const half = array.length / 2
// Base case or terminating case
if(array.length < 2){
return array
}
const left = array.splice(0, half)
return merge(mergeSort(left),mergeSort(array))
}
array = [4, 8, 7, 2, 11, 1, 3];
console.log(mergeSort(array));
[1, 2, 3, 4, 7, 8, 11]
Reference https://stackabuse.com/merge-sort-in-javascript
初學者入門學習的演算法 - 泡沫排序 Bubble Sort 如果相鄰元素的順序錯誤,則冒泡排序算法會重複交換相鄰元素 Reference 初學者入門學習的演算法 - 泡沫排序 Bubble Sort 泡沫排序演算法的運作如下:
比較相鄰的元素。如果第一個比第二個大,就交換他們兩個。 對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最後一對。這步做完後,最後的元素會是最大的數。 針對所有的元素重複以上的步驟,除了最後一個。 持續每次對越來越少的元素重複上面的步驟,直到沒有任何一對數字需要比較。 由於它的簡潔,泡沫排序通常被用來對於程式設計入門的學生介紹演算法的概念。
如果相鄰元素的順序錯誤,則冒泡排序算法會重複交換相鄰元素 冒泡排序常用於實現排序算法。氣泡中的每個元素都與其周圍的元素形成對比。以泡泡形式。該列表將通過算法進行處理。對具有 n 個元素的列表進行排序需要 N-1 遍。取一個包含 n 個元素的表 A,這些元素必須用某種氣泡排序。算法如下 • 在第 1 輪中,數字 A[0] 由 A[1] 組成,數字 A[1] 與 A[2] 進行比較,數字 A[2] 與 A[3] 進行比較,等等. 列表中最大的項放在第 1 輪的末尾,位於列表的最高索引處。 • A[0] 與第 2 輪中的 A[1] 進行比較,A[1] 與 A[2] 進行比較,依此類推。第二大項放在列表末尾的第二高索引上通過 2。 • 第 n-1 次移動將 A[0] 與 A[1]、A[1] 與 A[2] 進行比較,依此類推。傳球在底部結束。列表的第一個索引是列表中最小的項目。
var n = [282, 6, 88, 44, 33, 12, 15, 121, 351, 234, 99];
for (m = 0; m < 10; m++) {
for (j = 0; j < 10; j++) {
if (n[m] < n[j]) {
temp = n[m];
n[m] = n[j];
n[j] = temp;
}
}
}
hint = "<br>";
document.writeln("數列經泡沫排序後 .." + hint);
for (m = 0; m < 10; m++) {
document.writeln(n[m]);
document.writeln(hint);
}
Reference https://laptrinhx.com/
何謂 Git Submodule 先在 GitHub 建立好 子Repository,然後在主專案輸入指令 建議不先預留資料夾否則會無法建立 子Repository Clone 完成 如果你有多個子專案,請務必注意,此文件與你的其他文件(例如你的.gitignore文件)一起受版本控制。它與項目的其餘部分一起更新或取回。 Reference 主要會使用到 Git Submodule 是因為部落格是使用 GitHub Pages,是GitHub提供的一個網頁代管服務,其中 Jekyll 軟體可以用於將文檔轉換成靜態網頁,該軟體提供了將網頁上傳到GitHub Pages的功能可說是超級方便!
何謂 Git Submodule 簡單的來講,就是巢狀的 Git 結構,意思是主專案中又有一個子專案需要拆開來使用git,類似一種 Library 套件管理的概念,像是大家在開發新專案的時候,如果想要用到其他專案的程式碼時,像是主流的 CSS Framwork 如:Vuetify、Bootstrap、Element UI,這些大型套件都放在 Github 方便進行維護更新,從前的作法就是先 git clone 下來,把要的檔案分別複製到自己專案,但是這樣麻煩的問題就來了! 若不是用 npm 或 webpack 這種套件管理,假如官方有釋出新版本,那要如何更新呢?這時可別再下載zip手動更新了,這時候 Git Submodule 就是一個不錯的解決方案,幫助大家方便管理程式碼!
先在 GitHub 建立好 子Repository,然後在主專案輸入指令 正常來說當你有一個 Repository,裡面如果包有一個子 Repository的話。是不能用 Git Push 推送到 remote repository裡的,這可能會發生問題,因此這邊就要加入 Git Submodule 的指令操作。
讓我們首先在遠端建立好欲添加的子Repository。並複製http或SSH連結,在主專案裡輸入git submodule add來開起追蹤命令,在此示範建立子專案”subCase”:
建議不先預留資料夾否則會無法建立 $ git submodule add {子專案的repo.git} {選填:主專案中欲儲存的子資料夾之資料夾名稱}
Cloning into 'subCase'...
remote: Counting objects: 11, done.
remote: Compressing objects: 100% (10/10), done.
remote: Total 11 (delta 0), reused 11 (delta 0)
Unpacking objects: 100% (11/11), done.
Checking connectivity... done.
在默認地情況下,子專案會將子項目添加到與Repository同名的目錄中,在本例中為“subCase”。所以如果你希望它建立在其他資料夾,你可以在命令的末尾添加想要的資料夾名稱。
子Repository Clone 完成 Reactivating local git directory for submodule 'subCase'.
warning: LF will be replaced by CRLF in .gitmodules.
The file will have its original line endings in your working directory
如果你此時運行git status,你會注意到一些事情。
$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: .gitmodules
new file: subCase
然後在主專案的.git資料夾裡,可以注意到新.gitmodules文件的配置文件,為用於存儲項目 URL 和你將其拉入的本地子目錄之間的映射:
[submodule "subCase"]
path = subCase
url = https://github.com/test/subCase
如果你有多個子專案,請務必注意,此文件與你的其他文件(例如你的.gitignore文件)一起受版本控制。它與項目的其餘部分一起更新或取回。 Reference https://git-scm.com/docs/git-submodule
方法一: 取消與remote連接,重新連接後,並設定識別資料 方法二: 更換與遠短連接方式,重新請求設定 username 與 password 之前因為自己公司筆電跟自家桌機常常需要切換開發,導致我自己的個人部落格在不同電腦上要進行同步,或是在接手專案要維護的時候,準備要 git pull 卻出現錯誤。去google網路看是不是SSH的問題,但查了又不是此類的問題,如果你也剛好遇到此問題可以來試試以下這段:
$ git push origin master
ERROR: Repository not found.
fatal: Could not read from remote repository.
--------------
Please make sure you have the correct access rights
and the repository exists.
ERROR: Repository not found.
fatal: Could not read from remote repository.
上google了解是因為使用 ssh 連線到 GitHub 但可能出現 key 導致錯誤發生,不想再替換SSH或重新安裝的人,可以重新設定識別資料或是設置password來解決這個困擾。
方法一: 取消與remote連接,重新連接後,並設定識別資料
$ git remote add origin git@gitlab.com:XXX
$ git config --global user.name "John Doe"
$ git config --global user.email johndoe@example.com
方法二: 更換與遠短連接方式,重新請求設定 username 與 password # 先確定目前remote連結
$ git remote -v
# 若如果出現這樣,可發現之前用的是走 https 通道
origin https://github.com/{username}/{repo}.git (fetch)
origin https://github.com/{username}/{repo}.git (push)
# 接著試試(應該是不會給過)
$ git remote add origin git@github.com:{username}/{repo}.git
# 然後會說已經存在
fatal: remote origin already exists.
# 接著設定 set-url 修改為走模式 SSH 連線方式
$ git remote set-url origin https://github.com/{username}/{repo}.git
# 確認一下
git remote -v
# 代表成功替換
$ origin git@github.com:{username}/{repo}.git (fetch)
$ origin git@github.com:{username}/{repo}.git (push)
# 然後將專案 pull
$ git pull
# 伺服器就會詢問 GitHub 帳號密碼了
Username for 'https://github.com':
Password for 'https://github.com':
參考來源
1.6 開始 - 初次設定 Git https://git-scm.com/ Git – GitHub 出現 http://jsnwork.kiiuo.com/
單一程序瀏覽器時期 問題 進化:多程序瀏覽器時期 改進 現代瀏覽器架構 優勢 SOA 瀏覽器架構 彈性架構 瀏覽器渲染機制 渲染流程 Layer 分層與 Compositing 結語 References 「瀏覽器的進步使得我們能在網頁上實現越來越多的功能。」
作為 Web 工程師,尤其是前端開發者,了解瀏覽器的架構和渲染機制是非常重要的。這篇文章將帶你從瀏覽器的單一程序架構到多程序架構,再到現代的多層次架構,深入了解瀏覽器的演進過程。
單一程序瀏覽器時期 早期在2007年之前瀏覽器基本上都是單一程序架構。所有功能模組都運行在同一個程序中,這導致了不穩定性、不流暢性和安全性問題。
問題 不穩定性 :一個模組出問題會導致整個瀏覽器崩潰。不流暢性 :單一執行緒導致資源被獨佔,影響整體性能。安全性問題 :缺乏沙盒機制,容易被惡意程式攻擊。進化:多程序瀏覽器時期 2008 年,Chrome 推出了多程序架構,將渲染程序和插件程序獨立出來,通過 IPC 進行溝通。
改進 穩定性 :各個程序互相隔離,單一模組崩潰不會影響整體。流暢性 :每個 Tab 獨立運行在不同的渲染程序中,提升了性能。安全性 :引入沙盒機制,提升了安全性。現代瀏覽器架構 現代瀏覽器進一步將網路資源操作和 GPU 操作獨立出來,形成更加豐富的多程序架構。
優勢 性能提升 :多程序並行運行,提升了整體性能。更高的穩定性和安全性 :進一步隔離不同功能模組,提升了穩定性和安全性。SOA 瀏覽器架構 Chrome 團隊提出了以 SOA 為基礎的新架構,將各個功能模組作為服務運行,實現高內聚、低耦合、易擴展與易維護的特性。
彈性架構 高性能設備 :拆分成多個程序運行,提升穩定性和效能。低性能設備 :合併成單一程序運行,節省記憶體。瀏覽器渲染機制 現代瀏覽器的渲染機制包括 DOM Tree、CSSOM Tree、Render Tree、Layout Tree 和 Paint 階段。
渲染流程 生成 DOM Tree 生成 CSSOM Tree 生成 Render Tree 生成 Layout Tree Paint 畫面 Layer 分層與 Compositing 瀏覽器會根據 Layout Tree 產生 Layer Tree,並在 Compositor Thread 進行合成,提升渲染效能。
結語 瀏覽器的進步使得我們能在網頁上實現越來越多的功能。作為 Web 開發者,了解瀏覽器的架構和渲染機制,能夠幫助我們更好地開發高效能的網頁應用。
References Inside look at modern web browser (Part 1, 2, 3, 4) 浏览器工作原理与实践 Chrome Site Isolation Rendering Performance Reflow 和 Repaint 引發的性能問題 DOM Performance 客製化表單上傳至Google Sheet 步驟1. 建立一個Google表單 Google表單連結Google Sheet 進入後開啟瀏覽器的開發者工具 在form元素內層可以找到幾個隱藏的input POST請求 小結 今天我想分享一個既有趣又實用的應用,就是利用Google Sheet來充當表單內容的資料庫。我想許多讀者會猜測這將會是一個麻煩的過程,可能要經過許多繁雜的設置,不過事實是… 其實非常簡單又方便 如果想一探究竟的讀者就繼續往下看吧!
客製化表單上傳至Google Sheet 為什麼要這麼做? 基本上大部分的事情都是先有需求,再去因應需求找出對應的解法。因此今天在說明該怎麼做到把Google Sheet當作客製化表單資料庫以前,我們得先談談這樣的方法適合應用在哪些使用情境上。 大部分企業幾乎都會有自己的形象官網,而通常官網也會與企業提供的服務分開,為單純以展示資訊為主要目的的靜態形象頁面。同樣性質的網頁還有特定活動的宣傳網站,也是以展示活動資訊為主要目的,與網頁應用程式(web app)有很大的區別。不過雖然是以呈現資訊為主,這類型的網站通常會有一個例如「聯絡我們」的區塊,讓使用者填寫自己的聯絡資訊,搜集顧客資訊以挖掘更多潛在的商機,例如知名電動車品牌Tesla的官網:
我們都知道通常表單的運作是在提交時會發一個POST請求到後端API,再將資料儲存到後端資料庫裡。但是如果因為團隊人力配置因素或是開發者本身技術限制,沒辦法生出這樣一個API的話該怎麼辦呢?又或者即使有這樣的API,但要運用這些資料的人反而是非工程團隊的夥伴時,請他們下SQL查詢去撈資料好像又不是那麼實際或方便(當然還是有很多能協助達成這件事的工具啦),這時候如果採用文章標題的方法似乎蠻可行的:將客製化的表單內容上傳至Google Sheet中。像這樣資料提交數量不會很大的情況,就很適合這樣的做法,Google Sheet的操作介面也十分平易近人,適合所有人來使用。 了解這個方法適用的情況後,讓我們開始動手做吧!
步驟1. 建立一個Google表單 是的,你沒有看錯,不是Google試算表,是Google表單(Google Form)。在我們從客製化表單點擊提交後,我們會對一個URL發一個POST請求,這個URL就是Google表單的連結,URL中我們會帶查詢字串,我們都知道查詢字串會是鍵值對的形式,這邊的鍵會是Google表單各欄位的ID,值則是我們從客製化表單收集到的資訊,當我們完成這個請求後,就會自動將資料回覆到Google表單中,接著就是Google服務強大的地方了,它可以將Google表單收到的回覆同步到一個Google Sheet中,如此一來Google Sheet就成為一個簡單的儲存庫了。 讓我們總結一下這個方式 從客製化表單按下送出按鈕後,會對Google表單發一個POST請求,以查詢字串的方式將資料帶到Google表單回覆中,再利用Google服務相通的功能,將資料同步儲存到Google Sheet中。 不過其實除了一開始設定以外,之後的流程都可以忽略Google表單那層,我們可以看成從客製化表單送出後,資料就直接存到Google Sheet裡面了。
(在開始之前記得將表單權限設為所有人都可以存取喔!) 在建立Google表單之後,就可以來建立問題欄位,注意囉,這邊的欄位要跟你網頁上客製化表單的欄位一樣喔!這邊因為示範方便所以隨便新增兩個欄位。 接著點選回覆的分頁,有個Google Sheet的圖示,點擊創建一個與這個表單連結的試算表(其實也可以連結現有表單不需重新建立)
Google表單連結Google Sheet 接下來我們需要取得兩個東西: Google表單的ID 表單中各欄位的ID Google表單的ID
先點選右上角的「傳送」按鈕,再點選連結的傳送方式,會出現一段URL,以示範裡的例子來說,URL為 https://docs.google.com/forms/d/e/1FAIpQLSfniOOcWIeG4FsL14tqLoEfqz9oRYuGru8rwMvOhH2vs7UPPg/viewform?usp=sf_link 我們要的form ID即為/e後的那段字串,即是 1FAIpQLSfniOOcWIeG4FsL14tqLoEfqz9oRYuGru8rwMvOhH2vs7UPPg 表單中各欄位的ID 我們得取得Google表單中各欄位的ID,才能在POST請求時正確傳資料到該欄位,首先先進入上面拿到的用來分享表單的連結
https://docs.google.com/forms/d/e/1FAIpQLSfniOOcWIeG4FsL14tqLoEfqz9oRYuGru8rwMvOhH2vs7UPPg/viewform?usp=sf_link
進入後開啟瀏覽器的開發者工具 entry.979040326與entry.589442071就是我們要找的欄位ID,注意這邊隱藏input的順序是跟表單欄位的順序一樣的喔!
POST請求 必要的資料都拿到後就可以試著在客製化表單送出時發出POST請求了
import { stringify } from ' qs ' ;
// 上傳數據到Google表單的函數
export const uploadToGoogleSheet = ( formId : string , query : Record < string , unknown > ): Promise < void > => {
return new Promise (( resolve , reject ) => {
fetch ( `https://docs.google.com/forms/d/e/ ${ formId } /formResponse?& ${ stringify ( query )} &submit=SUBMIT` , {
method : ' POST ' ,
mode : ' no-cors ' , // Google只接受'no-cors'模式的表單提交
redirect : ' follow ' ,
referrer : ' no-referrer ' ,
})
. then (() => resolve ())
. catch (() => reject ());
});
};
// 處理表單提交的函數
const handleSubmit = ( values : any ) => {
const FORM_ID = ' 1FAIpQLSfniOOcWIeG4FsL14tqLoEfqz9oRYuGru8rwMvOhH2vs7UPPg ' ;
const query = {
' entry.979040326 ' : values . data1 , // 傳送使用者在表單填寫的資訊
' entry.589442071 ' : values . data2 ,
};
uploadToGoogleSheet ( FORM_ID , query )
. then (() => {
// 提交成功後的處理
console . log ( ' 數據成功提交到Google表單 ' );
})
. catch (() => {
// 提交失敗後的處理
console . error ( ' 提交數據到Google表單時出錯 ' );
});
};
程式碼其實相當簡單,我們只需要將剛剛拿到的form ID帶進URL中,再將各欄位的entry ID帶入查詢字串中當作鍵,值則給予使用者在客製化表單上輸入的值,POST請求成功後回到Google Sheet就會看到剛剛提交的值已經被記錄下來囉!
小結 雖然說這是一個沒什麼技術含量的分享,但我認為這樣的方式十分有趣,以某些使用情境來說也是非常適合的一種記錄表單資料的方式,Google表單雖然方便,但有時候總會因為缺乏「美感」或是獨立於我們網頁之外而使人卻步,如果你有類似的問題,不妨試試看本篇文章教的方法吧,希望這篇文章能夠幫助到螢幕前的你!
什麼是 Jekyll ? 打算使用 Jekyll 的朋友們,會建議熟悉 Git & Html & Markdown 使用的 Jekyll 特色呢? Github Pages & jekyll 技術介紹 強大特色 Jekyll 官方介紹 jekyll-theme Github Page 來說說 Github Pages 與 jekyll 好用的部落格功能吧~
什麼是 Jekyll ? Jekyll是基於Ruby Gem的解析引擎,能夠將樣板、liquid 語言、markdown轉換為 靜態網頁 的產生器。
打算使用 Jekyll 的朋友們,會建議熟悉 Git & Html & Markdown 使用的 Jekyll 特色呢? No more databases 不需要資料庫 Liquid Template 動態模板 Free hosting with GitHub Pages 只要學會git push 就可以丟到github page上 Markdown 好編寫 Github Pages & jekyll 技術介紹 Git, Github, Github Pages Git版本控制工具,Github是使用git版本控制項目的的虛擬主機服務 連結在此:http://pages.github.com/ Github Pages 是 Github 提供的服務,可以利用 Repository 建立自己的靜態頁面,其中不需要任何 databases 的 Jekyll 強大功能,在每次的 git push 後會將 markdown 轉換為頁面,所以 Jekyll 是很適合用來建立部落格等內容!
強大特色 快速 html靜態頁就是快速。 穩定 ”github” 這個品牌能不信嗎? 完全免費,可惜大部分的模板不怎麼美就是了… 容量無限 只要會git commit、git push。 Markdown是一種輕量級標記式語言,他在編寫完後就像是一般的文字檔,也可轉換成有效的XHTML(或者HTML)文件。 其易懂易讀的語法都是用標點符號組成,方便作為網站blog的寫作語言。附上相關範例 http://markdown.tw/ Jekyll 官方介紹 可於官網下來或在 git hub 搜尋相關主題下載下來使用,其資料夾編寫後會產生(如:_site等資料夾),再將此資料夾的靜態網頁上傳於 Repository 即可。 https://jekyllrb.com/
jekyll-theme Jekyll所使用的樣板語言是使用 Ruby 編寫,透過渲染器運行生成為靜態網站。本地端需要下載 ruby 來運行。以下官方提供模板範例可下載使用。 https://www.ruby-lang.org/zh_tw/ https://github.com/topics/jekyll-theme
Github Page 在發布Repository後,之後每次都只需要在本地端push文章就可以了!而每次push到github上的文章及Template,都會透過Jekyll server轉換為靜態的網站。
雄心壯志:全端工程師夢 迷茫時期:前端的價值何在? 重新定位:發掘自我價值 前端:表面簡單,內涵豐富 全端發展:權衡與選擇 站在職涯的十字路口,我不禁陷入了深思。作為一名網頁開發新手,該往前端還是後端方向邁進?這個問題困擾著我。回想起來,我的程式之旅始於前端,因為它能迅速呈現成果,給予我極大的成就感。然而,隨著時間推移,我開始探索後端領域,希望能夠全面掌握網頁運作的奧秘。
雄心壯志:全端工程師夢 初入程式世界,我雄心勃勃,立志成為一名全能的全端工程師。這個目標看似完美,直到我偶然看到一句話:”自稱全端的人往往樣樣通,樣樣鬆”。這句話如當頭棒喝,促使我重新審視自己的職涯規劃,也讓我開始深入探索網路開發的生態系統。
迷茫時期:前端的價值何在? 在研究過程中,我驚訝地發現網路上充斥著對前端開發者的質疑聲音。主要論點包括:
入行門檻低,人人都可以做 不需要深厚的計算機科學基礎 市場飽和,出現所謂的”前端難民”現象 這些言論讓我陷入了自我懷疑:選擇前端作為職業發展方向,我真的能在這個領域有所作為嗎?
重新定位:發掘自我價值 經過一番深思熟慮,我逐漸找到了答案。
前端:表面簡單,內涵豐富 深入了解後,我發現前端遠非外界想像的那樣簡單。近年來,前端技術日新月異,PWA、跨平台開發、WebAssembly等新技術層出不窮。瀏覽器功能日益強大,推動了前端的無限可能。性能優化成為關鍵課題,傳統網站正逐步被功能強大的Web應用取代。
我有幸在實習期間遇到了卓越的導師和優秀的團隊,他們讓我領悟到高質量代碼和優秀架構設計的重要性。這些經歷使我確信:在技術領域,價值源於個人的不斷探索和創新。
就前端工程師而言,有人專注於技術架構,有人擅長用戶體驗設計,每個人都能在自己的專長領域創造獨特價值。關鍵在於找准自己的定位,滿足市場的多元需求。
全端發展:權衡與選擇 經過深思,我認識到在有限時間內同時精通前後端確實極具挑戰。因此,我決定先在一個領域深耕細作,選擇最適合自己的發展方向。但這並不意味著要放棄學習其他技能。
如今,當被問及職業時,我會這樣回答:「我是一名網頁開發工程師,專注於前端技術,同時也在不斷學習後端知識。」我相信,一個優秀的前端工程師應該了解數據處理的原理,同樣,一個出色的後端工程師也應該關注數據在前端的呈現效果。這種全面的視角對於打造優質產品至關重要。
未來的道路還很長,也許幾年後我的職位會有所變化。但最重要的是,我不能忘記初心——用技術解決實際問題,分享知識,推動行業進步。最關鍵的是,保持對這個領域的熱愛和探索精神。我堅信,只要堅持不懈,終會在這個充滿機遇的行業中找到屬於自己的一席之地。
Pagination © 2021. All rights reserved.