สร้างอาร์เรย์ที่มีองค์ประกอบเดียวกันซ้ำหลายครั้ง


323

ใน Python โดยที่[2]list คือโค้ดต่อไปนี้จะให้ผลลัพธ์นี้:

[2] * 5 # Outputs: [2,2,2,2,2]

มีวิธีง่ายๆในการทำเช่นนี้กับอาร์เรย์ใน JavaScript?

ฉันเขียนฟังก์ชันต่อไปนี้เพื่อทำ แต่มีบางสิ่งที่สั้นกว่าหรือดีกว่า

var repeatelem = function(elem, n){
    // returns an array with element elem repeated n times.
    var arr = [];

    for (var i = 0; i <= n; i++) {
        arr = arr.concat(elem);
    };

    return arr;
};

4
สำเนาซ้ำที่เป็นไปได้: stackoverflow.com/questions/1295584/…
Larry Battle

เป็นไปได้ที่ซ้ำกัน: stackoverflow.com/questions/1877475/repeat-character-n-times
Benkinass

คำตอบ:


52

คุณสามารถทำได้เช่นนี้:

function fillArray(value, len) {
  if (len == 0) return [];
  var a = [value];
  while (a.length * 2 <= len) a = a.concat(a);
  if (a.length < len) a = a.concat(a.slice(0, len - a.length));
  return a;
}

มันเพิ่มอาร์เรย์เป็นสองเท่าในการวนซ้ำแต่ละครั้งเพื่อให้สามารถสร้างอาร์เรย์ขนาดใหญ่มากพร้อมการวนซ้ำสองสามครั้ง


หมายเหตุ: นอกจากนี้คุณยังสามารถปรับปรุงฟังก์ชันของคุณได้มากโดยใช้pushแทนconcatเช่นconcatจะสร้างอาร์เรย์ใหม่ในแต่ละการวนซ้ำ เช่นนี้ (แสดงเป็นตัวอย่างของวิธีที่คุณสามารถทำงานกับอาร์เรย์):

function fillArray(value, len) {
  var arr = [];
  for (var i = 0; i < len; i++) {
    arr.push(value);
  }
  return arr;
}

11
มันมากมีประสิทธิภาพมากขึ้นในการจัดสรรทั้งหมดของรายการขึ้นด้านหน้าที่มีนั้นกำหนดให้พวกเขาโดยดัชนีในวงคือarr = new Array(len); arr[i] = value;ด้วยวิธีนี้คุณจะจ่าย O (n) แทนที่จะต้องจัดสรรอาร์เรย์ซ้ำเมื่อโตขึ้น โดยทั่วไปจะดีกว่าเสมอเพื่อหลีกเลี่ยงการเพิ่มอาร์เรย์โดยการต่อท้ายเมื่อทำได้ ถ้าคุณรู้ขนาดสุดท้ายใช้มัน
Tom Karzes

26
Array.from({length:5}).map(x => 2)
noobninja

1
@ noobninja: ทางออกที่ดี; คุณควรป้อนใหม่เป็นคำตอบเพื่อให้สามารถอัปโหลดได้
jsalvata

693

ใน ES6 ใช้อาร์เรย์เติม ()วิธีการ

Array(5).fill(2)
//=> [2, 2, 2, 2, 2]

3
Internet Explorer และ Opera ยังไม่รองรับ
DenisKolodin

4
Node.js <= 3 ไม่รองรับสิ่งนี้
Junle Li

1
@DenisKolodin Opera ปัจจุบันทำ และขอบด้วย ดูตารางที่เข้ากันได้
Janus Troelsen

4
@Michael Array(5).fill([1,2,3]).flat()คุณสามารถทำมันได้ด้วย โปรดทราบว่าflat ()ยังคงอยู่ในช่วงทดลองและรองรับเบราว์เซอร์ไม่ดี
Niko Ruotsalainen

3
โปรดทราบว่าการโต้แย้งที่จะfillได้รับการประเมินครั้งเดียวดังนั้นArray(9).fill(someMutable)สร้างเก้าอ้างอิงถึงsomeMutableในอาร์เรย์ (กลายพันธุ์หนึ่งกลายพันธุ์ 'พวกเขาทั้งหมด')
Carl Smith

146
>>> Array.apply(null, Array(10)).map(function(){return 5})
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]
>>> //Or in ES6
>>> [...Array(10)].map((_, i) => 5)
[5, 5, 5, 5, 5, 5, 5, 5, 5, 5]

6
คำถามงี่เง่า แต่ทำไม Array (10) .map ใหม่ไม่ทำงาน?
blazkovicz


5
ด้วย ES6 สิ่งนี้สามารถ "อัปเกรด" เป็นArray(...Array(10)).map(() => 5)กับผู้ดำเนินการแพร่กระจายหรือไปยังArray.from(Array(10)).map(() => 5)
Christophe Vidal

4
ตามMDNคุณสามารถเป็นเช่นนี้:Array.from({length: 10}, () => 5);
Plusb Preco

2
@blazkovicz Array (10) สร้างอาร์เรย์ของlenght = 10โดยไม่มีคุณสมบัติที่นับได้ .mapใช้งานได้กับคุณสมบัติที่นับได้เท่านั้น .applyวิธีการใช้เวลาอาร์เรย์นี้และแผนที่ลงในarguments array(วัตถุอาร์เรย์เหมือน) จะถูกส่งผ่านไปยังArrayฟังก์ชั่นคอนสตรัค อาเรย์ของอาร์กิวเมนต์ไม่สามารถกระจัดกระจายได้ดังนั้นคุณสมบัติที่หายไปจะถูกตั้งค่าundefinedและนับเป็นจำนวนมาก ตอนนี้เราสามารถใช้งานได้ตามที่.mapตั้งใจไว้
CervEd

91

คุณสามารถลอง:

Array(6).join('a').split(''); // returns ['a','a','a','a','a'] (5 times)

อัปเดต (01/06/2018) :

ตอนนี้คุณสามารถมีชุดของตัวละครซ้ำ

new Array(5).fill('a'); // give the same result as above;
// or
Array.from({ length: 5 }).fill('a')

หมายเหตุ: ตรวจสอบเพิ่มเติมเกี่ยวกับการเติม (... )และจาก (... )เพื่อความเข้ากันได้และการสนับสนุนเบราว์เซอร์

อัปเดต (05/11/2019) :

อีกวิธีหนึ่งโดยไม่ใช้fillหรือfromทำงานได้กับสตริงที่มีความยาวเท่าใดก็ได้:

Array.apply(null, Array(3)).map(_ => 'abc') // ['abc', 'abc', 'abc']

เหมือนกับข้างต้นคำตอบ การเพิ่มเพื่อความสมบูรณ์


1
ดี สั้นและง่ายกว่า
Johann Echavarria

2
+1 เพื่อการจัดการที่ง่าย ความอัปยศที่คุณไม่สามารถสร้างอาร์เรย์ของสตริงว่างเปล่าได้ นอกเหนือจากสมาร์ทมาก ...
เร็วขึ้น

1
Array (6) .join ('a'). split ('a') ให้อาเรย์ของสตริงว่าง
Vivek

17
ใช้งานได้กับ 1 อักขระ char เท่านั้นดังนั้นจึงไม่ตอบคำถามอย่างสมบูรณ์
az_

3
@AlfonsoVergara: ใน Javascript สตริงเป็นชนิดดั้งเดิม (ค่าความหมาย) ไม่มีวิธีรับสองสตริงเพื่ออ้างอิงข้อมูลเดียวกัน (เนื่องจากสตริงไม่ได้อ้างอิงใน Javascript เพราะเป็นค่า) คุณต้องระวังซีแมนทิกส์อ้างอิงกับวัตถุและรายการ แต่ไม่ใช่กับสตริง
Quuxplusone

36

Array.from({length:5}, i => 1) // [1, 1, 1, 1, 1]

หรือสร้างอาร์เรย์ที่มีมูลค่าเพิ่มขึ้น

Array.from({length:5}, (e, i)=>i) // [0, 1, 2, 3, 4]


นิสัยดีนี่เป็นวิธีที่ดีที่สุดถ้าคุณต้องการให้องค์ประกอบเป็นพลวัต
IliasT

Array.from({length:5}, i => 1)=> iเป็นundefinedเพราะมันหมายถึงค่าที่ว่างเปล่าArray.from({length:5}, (e, i)=>i)=> eเป็นundefinedเพราะมันหมายถึงค่าที่ว่างเปล่า ควรArray.from({length:5}, v => 1)และArray.from({length:5}, (v, i)=>i)
Rafal Enden

33

ในlodashมันก็ไม่ได้แย่ขนาดนั้น:

_.flatten(_.times(5, function () { return [2]; }));
// [2, 2, 2, 2, 2]

แก้ไข : ดียิ่งขึ้น:

_.times(5, _.constant(2));
// [2, 2, 2, 2, 2]

แก้ไข : ดียิ่งขึ้น:

_.fill(Array(5), 2);

3
_.times (length, _.constant (value))
user1533401

1
จากเอกสาร: _.fill (Array (3), 2); ซึ่งอยู่ไม่ไกลจาก ES6
kert

15

[c] * n สามารถเขียนเป็น:

Array(n+1).join(1).split('').map(function(){return c;})

ดังนั้นสำหรับ [2] * 5

Array(6).join(1).split('').map(function(){return 2;})

ที่จริงแล้ว Array (6) .join (2) .split ('') จะง่ายกว่าไหม? ทำไมคุณต้องการแผนที่
แองเจล่า

4
ที่ส่งกลับ ["2", "2", "2", "2", "2"] แทน [2, 2, 2, 2, 2]
รู๊คฮง

10

คุณยังสามารถขยายการทำงานของ Array ได้เช่น:

Array.prototype.fill = function(val){
    for (var i = 0; i < this.length; i++){
        this[i] = val;
    }
    return this;
};
// used like:
var arry = new Array(5)​.fill(2);
// or
var arry = new Array(5);
arry.fill(2);


console.log(arry);​ //[2, 2, 2, 2, 2] 

ฉันควรทราบว่าการขยายการทำงานของวัตถุในตัวอาจทำให้เกิดปัญหาได้หากคุณทำงานกับห้องสมุดบุคคลที่สาม ชั่งน้ำหนักสิ่งนี้เป็นการตัดสินใจของคุณเสมอ


โปรดทราบว่าถ้าคุณส่งวัตถุไปยังfillแต่ละดัชนีในอาร์เรย์จะอ้างอิงถึงวัตถุเดียวกันดังนั้นการเปลี่ยนหนึ่งรายการจะเป็นการเปลี่ยนแปลงทั้งหมด นี่ไม่ใช่เรื่องยากเกินไปที่จะแก้ไขหากมีปัญหา
Shmiddty

ฉันไม่เข้าใจว่าทำไมผู้ใช้จาวาสคริปต์หลายคนจึงไม่ทราบถึงความต้องการที่จะไม่ทำหน้าที่ต้นแบบดั้งเดิม
brooNo

2
วิธีเติมได้รับการเพิ่มใน ES6 ดังนั้นฉันจะไม่แนะนำให้เพิ่มข้อมูลของคุณเองในต้นแบบคุณจะเขียนทับรุ่นที่เร็วขึ้นและมีความสามารถมากขึ้น
Janus Troelsen

1
@JanusTroelsen เพื่อหลีกเลี่ยงการเขียนทับจาวาสคริปต์หรือห้องสมุดบุคคลที่สามคุณสามารถตรวจสอบว่ามีอยู่ก่อนที่จะประกาศมัน if (!Array.prototype.fill) { }
Oliver

1
@JanusTroelsen คุณหมายถึงอะไร "real polyfill" ฉันใช้ polifyll ฉันหมายถึง: ตรวจสอบการตรวจจับคุณสมบัติและการนำไปใช้ในกรณีที่ไม่ใช่
Oliver


5

ในกรณีที่คุณจำเป็นต้องทำซ้ำอาร์เรย์หลายครั้ง:

var arrayA = ['a','b','c'];
var repeats = 3;
var arrayB = Array.apply(null, {length: repeats * arrayA.length})
        .map(function(e,i){return arrayA[i % arrayA.length]});
// result: arrayB = ['a','b','c','a','b','c','a','b','c']

แรงบันดาลใจจากคำตอบนี้


ใน es6 คุณสามารถทำ"abc". Repeat (3)
Janus Troelsen

4

ไม่มีวิธีที่ง่ายกว่า คุณต้องสร้างการวนซ้ำและผลักองค์ประกอบเข้าไปในอาร์เรย์


ขอบคุณ! ก่อนที่ฉันจะยอมรับจะpushดีกว่าหรือconcatดีกว่าในแง่ของประสิทธิภาพ?
Curious2learn

CONCAT ต้องตรวจสอบสองอาร์เรย์ PUSH เพิ่งเพิ่มองค์ประกอบอื่นดังนั้นฉันคาดว่า PUSH จะมีประสิทธิภาพมากกว่าโดยทั่วไป แต่สำหรับข้อมูลที่เป็นตัวจริงฉันคิดว่าคำตอบของ Guffa ช่วยได้
Diodeus - James MacFarlane

ไม่ต้องการลูปดูคำตอบของฉัน
Janus Troelsen

@ JanusTroelsen ไม่จำเป็นต้องวนซ้ำจนกว่าคุณจะต้องการวิธีที่มีประสิทธิภาพในการดำเนินการนี้ ของคุณเป็นหนึ่งในการฟ้องร้องที่ช้ากว่าที่คุณสามารถหาได้ push () ถึง [] เร็วที่สุด
chrilith

4

ใช้ฟังก์ชั่นนี้:

function repeatElement(element, count) {
    return Array(count).fill(element)
}
>>> repeatElement('#', 5).join('')
"#####"

หรือสำหรับรุ่นกะทัดรัดยิ่งขึ้น:

const repeatElement = (element, count) =>
    Array(count).fill(element)
>>> repeatElement('#', 5).join('')
"#####"

หรือสำหรับเวอร์ชันแกงกะหรี่:

const repeatElement = element => count =>
    Array(count).fill(element)
>>> repeatElement('#')(5).join('')
"#####"

คุณสามารถใช้ฟังก์ชั่นนี้กับรายการ:

const repeatElement = (element, count) =>
    Array(count).fill(element)

>>> ['a', 'b', ...repeatElement('c', 5)]
['a', 'b', 'c', 'c', 'c', 'c', 'c']

4

หากคุณต้องการทำซ้ำอาร์เรย์ให้ใช้ดังต่อไปนี้

Array.from({ length: 3 }).fill(['a','b','c']).flat()

จะกลับมา

Array(9) [ "a", "b", "c", "a", "b", "c", "a", "b", "c" ]

ผู้เยี่ยมชมที่ยอดเยี่ยมโดยใช้อาร์เรย์ที่มีอยู่สิ่งที่ฉันต้องการ
gneric


1

ฟังก์ชันนี้สร้างอาร์เรย์ขององค์ประกอบ (ความยาว) ที่แต่ละองค์ประกอบเท่ากับ (ค่า) ตราบเท่าที่ (ค่า) เป็นจำนวนเต็มหรือสตริงของจำนวนเต็ม เลขทศนิยมใด ๆ จะถูกปัดเศษ หากคุณต้องการตัวเลขทศนิยมให้แทนที่"parseInt ( " ด้วย " parseFloat ( "

function fillArray(length, intValue) {
     var vals = (new Array(length + 1)).join(intValue + '|').split('|').slice(0,length);
     for(var i = 0; i < length; i += 1) {
         vals[i] = parseInt(vals[i]);
     }
     return vals;
}

ตัวอย่าง:

fillArray(5, 7) // returns [7,7,7,7,7]
fillArray(5, 7.5) // returns [7,7,7,7,7]
fillArray(5, 200) // returns [200,200,200,200,200]

1

ฉันมีปัญหากับวิธีการดังกล่าวเมื่อฉันใช้อาร์เรย์เช่น

var array = ['foo', 'bar', 'foobar'];
var filled = array.fill(7);

//filled should be ['foo', 'bar', 'foobar', 'foo', 'bar', 'foobar', 'foo']

เพื่อให้ได้สิ่งนี้ฉันกำลังใช้:

Array.prototype.fill = function(val){
    var l = this.length;
    if(l < val){
        for(var i = val-1-l; i >= 0; i--){
            this[i+l] = this[i % l];
        }
    }
    return this;
};

นี้เป็นสิ่งที่ดี cycleแต่อาจจะมีการตั้งชื่อ
Drenmi

1

ฉันค้นพบสิ่งนี้ในวันนี้ในขณะที่พยายามสร้างอาร์เรย์ 2D โดยไม่ใช้ลูป ในการหวนกลับการเข้าร่วมอาร์เรย์ใหม่นั้นเรียบร้อย ฉันลองแมปอาเรย์ใหม่ซึ่งใช้งานไม่ได้ในแผนที่ข้ามสล็อตว่าง

"#".repeat(5).split('').map(x => 0)

อักขระ "#" สามารถเป็นอักขระเดี่ยวที่ใช้ได้ 5 จะเป็นตัวแปรสำหรับจำนวนองค์ประกอบที่คุณต้องการ 7 จะเป็นค่าที่คุณต้องการเติมอาเรย์ของคุณ

วิธีการเติมแบบใหม่นั้นดีกว่าและเมื่อฉันเขียนมันฉันไม่รู้ว่ามันมีอยู่จริง ฉันจะเขียนโพสต์บล็อกเกี่ยวกับการใช้เคล็ดลับนี้ควบคู่ไปกับการลดการทำสิ่งดีๆ

http://jburger.us.to/2016/07/14/functionally-create-a-2d-array/







-1

ฉันต้องการวิธีในการทำซ้ำ / วนรอบอาร์เรย์ (มีรายการ n) m ครั้ง

ตัวอย่างเช่นการกระจายรายชื่อ (ของบุคคล) ไปยังสัปดาห์ / เดือน สมมติว่าฉันมี 3 ชื่อและฉันต้องการให้พวกเขาทำซ้ำในหนึ่งสัปดาห์:

fillArray(["Adam", "Blair", "Curtis"], 7); // returns ["Adam", "Blair", "Curtis", "Adam", "Blair", "Curtis", "Adam"]

function fillArray(pattern, count) {
    let result = [];
    if (["number", "string"].includes(typeof pattern)) {
        result = new Array(5);
        result.fill(pattern);
    }
    else if (pattern instanceof Array) {
        for (let i = 0; i < count; i++) {
            result = result.concat(pattern);
        }
        result = result.slice(0, count);
    }
    return result;
}

fillArray("a", 5);        // ["a", "a", "a", "a", "a"]
fillArray(1, 5);          // [1, 1, 1, 1, 1]
fillArray(["a", "b"], 5); // ["a", "b", "a", "b", "a"]
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.