การสร้างวัตถุโดยการวนซ้ำผ่านอาร์เรย์สองตัว

ค่อนข้างตรงไปตรงมา

ฉันต้องสร้างฟังก์ชัน objOfMatches ที่ยอมรับสองอาร์เรย์และการโทรกลับ objOfMatches จะสร้างวัตถุและส่งคืน ในการสร้างวัตถุ objOfMatches จะทดสอบแต่ละองค์ประกอบของอาร์เรย์แรกโดยใช้การเรียกกลับเพื่อดูว่าเอาต์พุตตรงกับองค์ประกอบที่เกี่ยวข้อง (ตามดัชนี) ของอาร์เรย์ที่สองหรือไม่ หากมีข้อมูลที่ตรงกัน องค์ประกอบจากอาร์เรย์แรกจะกลายเป็นคีย์ในออบเจ็กต์ และองค์ประกอบจากอาร์เรย์ที่สองจะกลายเป็นค่าที่สอดคล้องกัน

function objOfMatches(array1, array2, callback) {
    //create obj
    var obj = {}

    //loop thru first array
    for(let i = 0; i < array1.length; i++) {
        for (let j = 0; j < array2.length; j++) {
            if (callback(array1[i]) === array2[j]) {                
                obj.array1[i] = array2[j];
            }
        }
    }
    return obj;
}

console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));
// should log: { hi: 'HI', bye: 'BYE', later: 'LATER' }

ดูค่อนข้างเรียบง่าย แต่ฉันไม่เข้าใจว่าทำไมมันถึงส่ง TypeError ในคอนโซล (TypeError: Cannot set property '0' of undefined)

ใครสามารถอธิบายสิ่งที่เกิดขึ้น?


person leonardofed    schedule 13.09.2018    source แหล่งที่มา
comment
ลอง obj[array1[i]] = array2[j];   -  person Ori Drori    schedule 13.09.2018
comment
@OriDrori เอ่อมันใช้งานได้ ฟังดูแปลกๆ แต่ obj.array1[i] = array2[j]; ดูเหมือนไม่ใช่ข้อผิดพลาดทางไวยากรณ์ ฉันผิดอย่างชัดเจน   -  person leonardofed    schedule 13.09.2018
comment
ไม่ใช่ แต่ความหมายไม่ใช่สิ่งที่คุณคิด obj.array1[i] = array2[j] ->ตั้งค่าดัชนี i ของอาร์เรย์คุณสมบัติ obj เป็นค่า และไม่ได้ตั้งค่าคีย์ตามชื่อของข้อความที่อยู่ในดัชนี i ในอาร์เรย์   -  person Ori Drori    schedule 13.09.2018
comment
มันเรียกว่าสัญกรณ์วงเล็บ คุณสามารถใช้มันเพื่อเข้าถึงหรือตั้งค่าคุณสมบัติของวัตถุได้   -  person oosniss    schedule 13.09.2018
comment
เหตุใด 'hello' จึงไม่เป็นส่วนหนึ่งของผลลัพธ์ที่คุณคาดหวัง   -  person connexo    schedule 14.09.2018
comment
แล้วทำไม howdy ถึงไม่อยู่ในนั้นด้วย? นี่เป็นอะไรก็ได้นอกจาก ค่อนข้างตรงไปตรงมา   -  person connexo    schedule 14.09.2018
comment
@connexo ดูการโทรกลับที่ถูกส่งผ่านไปยัง objOfMatches   -  person leonardofed    schedule 14.09.2018
comment
มันช่วยตัดบรรทัดยาวๆ ได้เสมอ ;)... ปรับคำตอบของฉันให้เหมาะสม   -  person connexo    schedule 14.09.2018


คำตอบ (3)


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

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

function objOfMatches(arr1, arr2, callback){
  return arr1.reduce((obj, current, index) => {
    if(arr2[index] === callback(current)) obj[current] = arr2[index]
    return obj
  }, {})
}

console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));

person Mark    schedule 13.09.2018
comment
ใส่มาร์กเรียบร้อย - person leonardofed; 14.09.2018

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

const x = ['hi', 'howdy', 'bye', 'later', 'hello'],
      y = ['HI', 'Howdy', 'BYE', 'LATER', 'hello'];

console.log(x.reduce((a,v,i)=>Object.assign(a,{[v]:y[i]}),{}))

หากคุณต้องการตรวจสอบการมีอยู่และตำแหน่งของการแข่งขัน นี่คือสิ่งที่คุณต้องแก้ไขเพื่อให้ Array.prototype.reduce ทำงานสำหรับคุณ:

const x = ['hi', 'later', 'howdy', 'bye', 'hello', 'foo'],
      y = ['HI', 'baz', 'Howdy', 'BYE', 'LATER', 'hello', 'bar'];

console.log(x.reduce((a,v)=> {
    let i = y.indexOf(v.toUpperCase())
    return i === -1 ? a : Object.assign(a, {[v]:y[i]})
  },{}
))

person connexo    schedule 13.09.2018

ตามแนวทางของคุณ คุณควรใช้ obj[array1[j]] = array2[i] นี่คือตัวอย่าง:

function objOfMatches(array1, array2, callback) {
    //create obj
    var obj = {}

    //loop thru first array
    for(let i = 0; i < array1.length; i++) {
        for (let j = 0; j < array2.length; j++) {
            if (callback(array1[i]) === array2[j]) {   
                if(!array1[j] in obj) obj[array1[j]]  = [] 
                obj[array1[j]] = array2[i];
            }
        }
    }
    return obj;
}

console.log(objOfMatches(['hi', 'howdy', 'bye', 'later', 'hello'], ['HI', 'Howdy', 'BYE', 'LATER', 'hello'], function(str) { return str.toUpperCase(); }));

person Emeeus    schedule 13.09.2018
comment
สวัสดี Emeeus โซลูชันนี้ค่อนข้างให้คำแนะนำ คุณช่วยอธิบายคำสั่งซ้อนกัน if เพิ่มเติมอีกหน่อยได้ไหม? โดยเฉพาะส่วนนี้: if(!array1[j] in obj) obj[array1[j]] = [] obj[array1[j]] = array2[i]; ขอบคุณ - person Codestudio; 06.07.2020