国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專(zhuān)欄INFORMATION COLUMN

一道面試題引起的思考

snowLu / 2773人閱讀

摘要:這個(gè)時(shí)候查了下正則表達(dá)式的文檔文檔點(diǎn)擊這里,發(fā)現(xiàn)有一個(gè)方法,可以返回匹配成功的結(jié)果。那么我來(lái)總結(jié)下文章想表達(dá)的內(nèi)容對(duì)于具有固定格式的字符串,可以考慮使用正則表達(dá)式來(lái)識(shí)別和匹配。

今天在認(rèn)真干(劃)活(水)的時(shí)候,看到群里有人發(fā)了一道頭條的面試題,就順便看了一下,發(fā)現(xiàn)挺有意思的,就決定分享給大家,并且給出我的解決方案和思考過(guò)程。

題目如下:

實(shí)現(xiàn)一個(gè)get函數(shù),使得下面的調(diào)用可以輸出正確的結(jié)果

const obj = { selector: { to: { toutiao: "FE Coder"} }, target: [1, 2, { name: "byted"}]};

get(obj, "selector.to.toutiao", "target[0]", "target[2].name");
// [ "FE Coder", 1, "byted"]

乍眼一看,這不就是實(shí)現(xiàn)一個(gè)lodash.get方法嗎?看上去好像很簡(jiǎn)單。所以我就開(kāi)始寫(xiě)了第一個(gè)版本。思想其實(shí)很簡(jiǎn)單,遍歷傳進(jìn)來(lái)的參數(shù),使用split將每一個(gè)參數(shù)分隔開(kāi),然后遍歷取值,最終返回結(jié)果。

function get(data, ...args) {
    return args.map((item) => {
        const paths = item.split(".");
        let res = data;
        paths.map(path => res = res[path]);
        return res;
    })
}

一運(yùn)行,果不其然,報(bào)錯(cuò)了。

后來(lái)仔細(xì)看了一下提供的測(cè)試代碼,發(fā)現(xiàn)居然有target[0]這種東西。。居然還帶了個(gè)數(shù)組索引。

冷靜分析一下,對(duì)于后面帶了個(gè)索引的類(lèi)型,比如"target[0]",我們肯定是要特殊對(duì)待的。所以,我們首先得先識(shí)別到這種特殊的類(lèi)型,然后再對(duì)它進(jìn)行額外處理。

這個(gè)時(shí)候,很快的就可以想到使用正則表達(dá)式來(lái)做這個(gè)事情。為什么呢?因?yàn)橄襁@種帶有索引的類(lèi)型,他們都有一個(gè)特色,就是有固定的格式:[num],那么我們只需要能構(gòu)造出可以匹配這種固定格式的正則,就可以解決這個(gè)問(wèn)題。

對(duì)于這種格式,不難想到可以用這個(gè)正則表達(dá)式來(lái)做判斷:/[[0-9]+]/gi,可是我們還需要將匹配值取出來(lái)。這個(gè)時(shí)候查了下正則表達(dá)式的文檔(文檔點(diǎn)擊這里),發(fā)現(xiàn)有一個(gè)match方法,可以返回匹配成功的結(jié)果。那么就讓我們來(lái)做個(gè)測(cè)試:

const reg = /[[0-9]+]/gi;
const str = "target[123123]";
const str1 = "target[]"

if (reg.test(str)) {
    console.log("test success");
}

if (!reg.test(str1)) {
    console.log("test fail");
}

const matchResult = str.match(reg);
console.log(matchResult); // ["[123123]"]

誒,我們現(xiàn)在已經(jīng)找到了解決這種問(wèn)題的方法,那讓我們趕緊來(lái)繼續(xù)改進(jìn)下代碼。

function get(data, ...args) {
    const reg = /[[0-9]+]/gi;
    return args.map((item) => {
        const paths = item.split(".");
        let res = data;
        paths.map((path) => {
                  if (reg.test(path)) {
                    const match = path.match(reg)[0];
                    // 將target[0]里的target儲(chǔ)存到cmd里
                    const cmd = path.replace(match, "");
                    // 獲取數(shù)組索引
                    const arrIndex = match.replace(/[[]]/gi, "");
                    res = res[cmd][arrIndex];
                  } else {
                    res = res[path];
                  }
        });
        return res;
    });
}

const obj = { selector: { to: { toutiao: "FE Coder"} }, target: [1, 2, { name: "byted"}]};

console.log(get(obj, "selector.to.toutiao", "target[0]", "target[2].name"));

寫(xiě)完趕緊運(yùn)行一下,完美,輸出了正確的結(jié)果了。那么到這里就結(jié)束了?

改進(jìn)

可是總感覺(jué)有點(diǎn)不妥,感覺(jué)事情沒(méi)有那么簡(jiǎn)單。一般來(lái)說(shuō),面試題除了考驗(yàn)?zāi)憬鉀Q問(wèn)題的能力之外,可能還考驗(yàn)著你思考問(wèn)題的全面性、嚴(yán)謹(jǐn)性。像上面那種寫(xiě)法,如果用戶(hù)傳入了一個(gè)不存在的path鏈或者一些其他特殊情況,就可能導(dǎo)致整個(gè)程序crash掉。想下lodash.get調(diào)用方式,即使你傳入了錯(cuò)誤的path,他也可以幫你做處理,并且返回一個(gè)undefined。因此,我們還需要完善這個(gè)方法。

function get(data, ...args) {
    const reg = /[[0-9]+]/gi;
    return args.map((item) => {
        const paths = item.split(".");
        let res = data;
        paths.map(path => {
            try {
                if (reg.test(path)) {
                    const match = path.match(reg)[0];
                    const cmd = path.replace(match, "");
                    const arrIndex = match.replace(/[[]]/gi, "");
                    res = res[cmd][arrIndex];
                } else {
                    res = res[path];
                }
            } catch (err) {
                console.error(err);
                res = undefined;
            }
        });
        return res;
    });
}

在這里,我們對(duì)每一個(gè)path的處理進(jìn)行了try catch處理。若出錯(cuò)了,則返回undefined。哇,這樣看起來(lái)就比較穩(wěn)了。

那么,有沒(méi)有別的解決方法呢?

群里有一個(gè)大佬提出了一種更簡(jiǎn)單也很取巧的解決方案,就是通過(guò)構(gòu)建一個(gè)Function解決這個(gè)問(wèn)題(Function的詳細(xì)介紹點(diǎn)擊這里)。由于代碼很簡(jiǎn)單,我就直接貼出來(lái)了:

function get(data, ...args) {
    const res = JSON.stringify(data);
    return args.map((item) => (new Function(`try {return ${res}.${item} } catch(e) {}`))());
}

const obj = { selector: { to: { toutiao: "FE Coder"} }, target: [1, 2, { name: "byted"}]};

console.log(get(obj, "selector.to.toutiao", "target[0]", "target[2].name", "asd"));

看完之后,就兩個(gè)字,牛逼。

這種方法我承認(rèn)一開(kāi)始我確實(shí)沒(méi)想到,確實(shí)是很奇技淫巧。不過(guò)仔細(xì)思考了下,其實(shí)很多框架都用到了這個(gè)奇技淫巧。比如說(shuō)vue里,就使用new Function的方式來(lái)動(dòng)態(tài)創(chuàng)建函數(shù),解決執(zhí)行動(dòng)態(tài)生成的代碼的問(wèn)題。

再比如說(shuō),F(xiàn)unction.prototype.bind方法里(我寫(xiě)了個(gè)類(lèi)似的bind方法:倉(cāng)庫(kù)),也使用了Function來(lái)解決一些問(wèn)題(fn.length丟失問(wèn)題)。說(shuō)明這個(gè)東西還是挺有用的,得學(xué)習(xí)了解一波,說(shuō)不定哪天就用到了。

更新

有人提到了那種Function的方式?jīng)]辦法處理以下的處理:

let obj = {time : new Date(), a : "this is a", b : 30};

因?yàn)镴SON.stringfy后,Date、Function和RegExp類(lèi)型的變量都會(huì)失效。對(duì)于這種情況,評(píng)論區(qū)有個(gè)大佬(馮恒智)也提到了一種很好的解決方案:

function get(data, ...args) {
    return args.map((item) => (new Function("data",`try {return data.${item} } catch(e) {}`))(data));
}

除此之外,?代碼宇宙提出了另一種解決方案,就是將"target[0]"分為兩個(gè)key,也很簡(jiǎn)單粗暴,就是將在split之前,將字符串里的"["替換為".",將"]"直接去掉。這樣就可以將"target[0]"變?yōu)?target.0"。具體代碼如下:

function get(data, ...args) {
    return args.map((item) => {
                let res = data;
                item
                    .replace(/[/g, ".")
                    .replace(/]/g, "")
                    .split(".")
                    .map(path => res = res && res[path]);
        return res;
    })
}

而且這兩種方式的好處在于,它也可以處理多維數(shù)組的情況。

總結(jié)

學(xué)習(xí)完之后,最重要就是要總結(jié),只有總結(jié)下來(lái)了,知識(shí)才是你自己的。那么我來(lái)總結(jié)下文章想表達(dá)的內(nèi)容:

對(duì)于具有固定格式的字符串,可以考慮使用正則表達(dá)式來(lái)識(shí)別和匹配。

實(shí)現(xiàn)一個(gè)功能的時(shí)候,不要只考慮正常情況,要多考慮一些非正常情況,比如輸入格式不對(duì)、用戶(hù)不按套路來(lái)或者因?yàn)橐恍┢嫫婀止值氖虑閳?bào)錯(cuò)。并且能對(duì)可預(yù)見(jiàn)的非正常情況做一個(gè)容錯(cuò)處理。

有時(shí)候還是可以多學(xué)習(xí)了解一下一些黑科技(比如Function),說(shuō)不定哪天就可以用它來(lái)解決問(wèn)題。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/40215.html

相關(guān)文章

  • 一道面試引起思考

    摘要:這個(gè)時(shí)候查了下正則表達(dá)式的文檔文檔點(diǎn)擊這里,發(fā)現(xiàn)有一個(gè)方法,可以返回匹配成功的結(jié)果。那么我來(lái)總結(jié)下文章想表達(dá)的內(nèi)容對(duì)于具有固定格式的字符串,可以考慮使用正則表達(dá)式來(lái)識(shí)別和匹配。 今天在認(rèn)真干(劃)活(水)的時(shí)候,看到群里有人發(fā)了一道頭條的面試題,就順便看了一下,發(fā)現(xiàn)挺有意思的,就決定分享給大家,并且給出我的解決方案和思考過(guò)程。 題目如下: 實(shí)現(xiàn)一個(gè)get函數(shù),使得下面的調(diào)用可以輸出正確...

    xiaoqibTn 評(píng)論0 收藏0
  • 一道面試引起思考

    摘要:這個(gè)時(shí)候查了下正則表達(dá)式的文檔文檔點(diǎn)擊這里,發(fā)現(xiàn)有一個(gè)方法,可以返回匹配成功的結(jié)果。那么我來(lái)總結(jié)下文章想表達(dá)的內(nèi)容對(duì)于具有固定格式的字符串,可以考慮使用正則表達(dá)式來(lái)識(shí)別和匹配。 今天在認(rèn)真干(劃)活(水)的時(shí)候,看到群里有人發(fā)了一道頭條的面試題,就順便看了一下,發(fā)現(xiàn)挺有意思的,就決定分享給大家,并且給出我的解決方案和思考過(guò)程。 題目如下: 實(shí)現(xiàn)一個(gè)get函數(shù),使得下面的調(diào)用可以輸出正確...

    hlcc 評(píng)論0 收藏0
  • 一道多線(xiàn)程面試引起自我救贖

    摘要:重溫一個(gè)面試題內(nèi)容數(shù)組內(nèi)容為數(shù)組內(nèi)容為個(gè)英文字母,使用兩個(gè)線(xiàn)程分別輸入兩個(gè)數(shù)組,打印內(nèi)容為這樣的規(guī)律提取一下核心內(nèi)容,去除次要內(nèi)容兩個(gè)線(xiàn)程需要交替執(zhí)行,打印數(shù)字的線(xiàn)程需要先執(zhí)行,數(shù)組打印完畢后線(xiàn)程需要結(jié)束。 一道多線(xiàn)程面試題引起的自我救贖 近日去一個(gè)知名互聯(lián)網(wǎng)企業(yè)參加面試,之前準(zhǔn)備多多信心滿(mǎn)滿(mǎn),但是面試一開(kāi)始就是一道不起眼的編程題 數(shù)組A內(nèi)容為 1,2,3,4...52 ,數(shù)組B內(nèi)容...

    BaronZhang 評(píng)論0 收藏0
  • 「今日頭條」前端面試和思路解析

    摘要:一篇文章和一道面試題最近,有篇名為張圖幫你一步步看清和的執(zhí)行順序的文章引起了我的關(guān)注。作者用一道年今日頭條的前端面試題為引子,分步講解了最終結(jié)果的執(zhí)行原因。從字面意思理解,讓我們等等。當(dāng)前的最新版本,在這里的執(zhí)行順序上,的確存在有問(wèn)題。 一篇文章和一道面試題 最近,有篇名為 《8張圖幫你一步步看清 async/await 和 promise 的執(zhí)行順序》 的文章引起了我的關(guān)注。 作者用...

    寵來(lái)也 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<