標籤:

如何不使用loop循環,創建一個長度為100的數組,並且每個元素的值等於它的下標?

這是昨天參加阿里筆試的題目,我當初寫下的答案如下:

var a = new Array(100);

a = a.map(function(item, index) {

return index;

});

本以為是正確的,但是後來回到學校後,使用控制台列印一下,竟然是一個空數組,如下:

求大神指教!


這東西生成的是稀疏數組。

按照你的思路。

在Array(100)的基礎上,改成Array.from(Array(100))就可以返回密集數組了。

不過他說不能用loop,用map會不會太直接啊,講道理map也算loop吧 。

要我就用sort之類的會比較委婉。

不過出題人應該把遞歸給禁用掉才好。

----------------------------------------

補充一下,創建一個空的密集數組最正確姿勢應該用:

Array.from({length:100})

如果用:

Array.apply(null,{length:100})

會加分;

ES6可以用spread拓展運算符:

[...Array(100)]

最後附帶一下我 答案:

es5版:

/*
* Object.keys(Array.from({length:100}));
@missFM 說得對,Array.from是es6的,不能這裡用
*/
Object.keys(Array.apply(null,{length:100}));
// 這裡補充說明一下為什麼我認為Array.apply(null,{length:100})會加分,原因在於{length:100}這種寫法屬於鴨子類型,是es5才支持,老瀏覽器必須傳一個真正的Array(100) 這樣進去才行,相對比較消耗性能。

es6版:

Array.from(Array(100).keys())

或者

[...Array(100).keys()]

這應該是最短代碼的了

----------------------------------------

有一個很污的寫法:

Number.prototype[Symbol.iterator] = function() {
return {
v: 0,
e: this,
next() {
return {
value: this.v++,
done: this.v &> this.e
}
}
}
}

然後就可以:

[...100]


用所謂函數式語言的,用遞歸實現循環的思路就行了

function reduce(prev, curr) {
if (curr &>= 100) {
return prev
}
prev.push(curr)
return reduce(prev, curr + 1)
}

var arr = reduce([], 0)

當然,這是最樸素的方法,可以玩的方法還是挺多的

追加:

當然上面的那個實在太無聊了,我本來想用goto的,結果想起來,JS不支持goto,fuck JS,寶寶不開心了::&>_&<::。

那麼我只能讓它「支持」goto了,於是有了下面的代碼

function VM() {
this.stack = []
this.cs = []
this.pc = 0
this.ax = undefined
this.bx = undefined
}
VM.prototype.run = function(codes) {
this.cs = codes
this.pc = 0
return this.interpret()
}
VM.prototype.interpret = function() {
var vm = this
var instruction = vm.cs[vm.pc]
var op = instruction[0]
var ops = instruction.slice(1)

switch (op) {
case "jl":
if (vm.ax &< vm.bx) { vm.pc = ops[0] return vm.interpret() } case "inc": vm.ax++ break case "ld": vm[ops[0]] = ops[1] break case "push": vm.stack.push(vm[ops[0]]) break case "pop": vm[ops[0]] = vm.stack.pop() break case "arr_push": vm.bx.push(vm.ax) break case "ret": return vm.ax break default: throw "wtf??" } vm.pc++ return vm.interpret() } function make_a_100_len_array_without_fucking_loop() { var codes = [ ["ld", "ax", 0], // 0 ["ld", "bx", []], // 1 ["push", "bx"], // 2 ["push", "ax"], // 3 ["pop", "ax"], // 4 ["pop", "bx"], // 5 ["arr_push"], // 6 ["inc"], // 7 ["push", "bx"], // 8 ["push", "ax"], // 9 ["ld", "bx", 100],// 10 ["jl", 4], // 11 ["pop", "bx"], // 12 ["pop", "ax"], // 13 ["ret"] ] var vm = new VM() return vm.run(codes) } var arr = make_a_100_len_array_without_fucking_loop()

當然,還是沒有用循環。

寫了這麼多,沒有功勞也有苦勞啊,快點贊T_T


Array 的不少方法會跳過 undefined 確實是個著名的坑……

直接 map(just copy and paste to try)

"".split("").map(function (v, i) { return i; });

Array.fill

Array(100).fill("naive").map(function (v, i) { return i; });

Generator

function* angry(i) {
yield i;
if (i &< 99) { yield* angry(i + 1); } }; Array.from(angry(0));

遞歸

(function wallace (i) { return (i &< 0) ? [] : wallace(i - 1).concat(i); })(99);

尾遞歸

(function mistake (i, acc) { return (i &< 100) ? mistake(i + 1, acc.concat(i)) : acc; })(0, []);

我去面試我就給他寫個 Y combinator

(function (excited) {
return function (f) {
return f(f);
}(function (f) {
return excited(function (x) { return (f(f))(x); });
});
})(function (excited) {
return function(i) {
return (i &< 0) ? [] : excited(i - 1).concat(i); } })(99);


這麼多人贊的嗎~其實巧妙的方法不是沒有。

class array {

public:

int operator[](size_t index) {

return index;

}

};

還可以做得更騷,但手機碼字就懶得擼了(並不是因為買不起電腦啊!是因為睡前才刷的知乎)

//////以下是原答案//////

告訴你標準答案。手機碼字…將就著看吧…

int arr[] = {0, 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};

如果打表的成本低,那就打表。


占坑混眼熟:

Object.keys(new Int8Array(100)).map(Number);

setTimeout 派系

var i = 0;
var a = [];
var timer = setInterval(function () {
a[i] = i++;
if (i &>= 100) {
clearInterval(timer);
console.log(a);
}
}, 1);

var a = [];
var i = 0;
function step(timestamp) {
if (i &< 100) { a[i] = i++; requestAnimationFrame(step); } else { console.log(a); } } requestAnimationFrame(step);

實驗室派系

" ".repeat(100).split("").map(Object.call, Number); // only chrome

瀏覽器賭博派系

document.body.innerHTML.substr(0, 100).split("").map(Object.call, Number);


Object.keys(String(Array(101)));


const _f = (n, l) =&> n &<= 0 ? l : _f(n-1, [n].concat(l)); const f = (n) =&> _f(n, []);
f(10) // =&> [1,2,3,4,5,6,7,8,9,10]


用eval來模擬goto,強行不算遞歸!

var target = [];

var command = `
if (target.length &< 100) { target.push(target.length); eval(command); }`; -&> eval(command);

-&> target
&<- [0, 1 ...99]


@kmxz 的第一個方法

回復不可以傳圖

真相


Array.apply(null, {length: 100}).map(Number.call, Number)
Array.apply(null, {length: 100}).map(Object.call, Number)

補充下:

主要是利用一個Number.call(undefined, index, array)這樣一個思想,後面一個Number是為了在map中綁定需要的對象


不用循環用遞歸唄

你用foreach不還是loop嗎?


並沒有說明語言啊……不過一般來說給數組中所有元素賦值無外乎遍歷和遞歸,既然不用遍歷(考慮到各種容器底層實現也是遍歷居多),那麼用遞歸就好了。

int assign(int arr[],int idx){
return (idx&<0)?idx:(arr[idx]=assign(arr,idx-1)+1); }


來答一下為什麼對於`new Array(n)`創建的數組用`map`方法無效,有人說是跳過undefined,有人說跳過空位

[ECMAScript-262 5.1](http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.19)中對Array.prototype.map(callbackfn [, thisArg ])方法的描述有一句是:

&>`callbackfn` is called only for elements of the array which actually exist; it is not called for missing elements of the array.

在`map`方法的運算步驟定義中也有一句:

8. Repeat, while k &< len

a. Let Pk be ToString(k).

b. Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.

c. If kPresent is true, then

...

在為數組中每個元素執行`callbackfn `之前,會先判斷這個元素是否在數組中實際存在(actually exist),判斷的方法就是調用內部方法[[HasProperty]]。

也可以使用Object.prototype.hasOwnProperty寫一段代碼說明:

var arr = [undefined, undefined];
arr.hasOwnProperty(0); // true
arr.hasOwnProperty(1); // true
arr.hasOwnProperty(2); // false

var arr2 = new Array(2);
arr2.hasOwnProperty(0); // false
arr2.hasOwnProperty(1); // false

可以看到通過`new Array(2)`創建的數組實際是不存在元素的,所以`map`方法中的`callbackfn`不會執行

不是說知乎回答支持markdown的么,我記錯了還是用錯了?


有循環為啥不用?

用遞歸?這屬於沒事找事。

如果是我的話,我就回答,用循環,並且用 generator ,來咬我啊。如果 js 有 list comprehension 就更好了。


我能封裝嗎?

int GetTheValueOfAnElementByIndexFromAnArrayInWhichTheValueOfAnyElementIsEqualToItsIndex(int index) {

return index;

}


這道題TM找抽啊,到底要表達什麼意思?對於不同的語言有不同的解決方法:

1、C/C++:可以直接malloc一片內存區域,然後直接給這片內存刷默認值(大概需要用到宏),然後把這片內存的指針直接扔給數組(內存管理這方面還是C/C++的夠直接);

2、面向對象語言(Java、C#之類):TM不用loop循環可以用對象嵌套應用、再不濟也可以用遞歸啊;

3、腳本語言(Python之類):老子不用loop循環那就是找腳本語言類庫里自帶的那些偏門的特性咯?TM我還知道茴香豆的四種寫法,你為啥不考這個?


Object.keys(new Int8Array(100))


我來玩一玩

首先是Array.map

new Array(101).join("1").split("").map(function(v,i){return i})

當然forEach也行

p=new Array(101).join("1").split("")
p.forEach(function(v,i,a){a[i]=i})
console.log(p)

把合了再分改成fill也行

new Array(100).fill("").map(function(v,i){return i})

遞歸也行

(function f(i){if(i==0){return []};a=f(i-1);a.push(i-1);return a})(100)

對了還有Array.reduce

new Array(100).fill("").reduce(function(l,n,i,a){l.push(i);return l},[])

以及Array.reduceRight

new Array(100).fill("").reduceRight(function(l,n,i,a){l.push(99-i);return l},[])

ES6的話可以用Array.keys

[...new Array(100).keys()]

(估計是最短的了)

還有String.repeat

" ".repeat(100).split("").map((v,i)=&>i)

還可以這樣

(f=(i)=&>i==0?[]:[...f(i-1),i])(99)

還有什麼想起來再寫


--

出題人路過...

因為是校招的題目, 不會考太深的東西,

這裡其實就是想考慮下解題思路而已, 然後看看對 ES5/ES6 的一些方法是否有了解.

--


我去尾遞歸不算loop啊!長見識。。。。


推薦閱讀:

菜鳥想學計算機要從哪方面開始入手?
足球經理《Football Manager》的比賽模擬原理是什麼?
如何玩轉github?
GitHub 上有些什麼好玩的項目?
C語言中既然""與空格『 』是不一樣的,那為什麼在字元串問題中,scanf中還不能讀入空格?

TAG:JavaScript | 編程 |