2015-04-14 20 views
2

我想構建一個3層功能: 首先,數組列出了可用的工作室(數組稱爲'工作室')。 其次,另一個數組列出了用戶選擇的研討會(該陣列稱爲'selectedWorkshops')。 第三,我有一個名爲'registeredWorkshops'的最終數組。從數組中刪除匹配對象,同時將它們添加到另一個數組

當我的函數運行時,我想將'selectedWorkshops'中的對象添加到'registeredWorkshops',然後我想從'selectedWorkshops'和'workshop'中的任何匹配元素中刪除'selectedWorkshops'中的任何對象。因此,那些曾經存在於「精選車間」和「車間」中的物品現在只存在於「註冊車間」中。

這裏是我到目前爲止有:

addRemoveWorkshops = function(){ 
    var numberOfWorkshops = selectedWorkshops.length; 
    for(var i = 0; i < numberOfWorkshops; i++){ 
     registeredWorkshops.push(selectedWorkshops[i]); 
     for(var j = 0, arrayLength = workshops.length; j < arrayLength; j++) { 
      var searchTerm = selectedWorkshops[i].WorkshopId; 
      if (workshops[j].WorkshopId === searchTerm) { 
       workshops = workshops.slice(j); 
      } 
     } 
     selectedWorkshops = selectedWorkshops.slice(i); 
    } 
}; 
addRemoveWorkshops(); 

但功能沒有出現正常工作。它似乎並沒有刪除正確的研討會,而只是將其中一個選定的研討會添加到註冊的研討會。我究竟做錯了什麼?

這裏有一個codepen示範:http://codepen.io/trueScript/pen/GgVWMx

+0

我認爲你不能調用array.slice(i)或array.slice(J),當i或j值爲零 –

+1

@TheGuest你可以,但它只是返回一個空數組。 –

+0

@DanPrince我的意思是在這種情況下 –

回答

2

如果這是不可能的其他屬性添加到對象(按my other answer),那麼我會解決它像這樣:

function registration(workshops, selected, registered) { 

    // add the selected workshops to registered 
    selected.forEach(function(workshop) { 
    registered.push(workshop); 
    }); 

    // remove them from the other lists 
    registered.forEach(function(workshop) { 
    removeWorkshop(selected, workshop); 
    removeWorkshop(workshops, workshop); 
    }); 

} 

function removeWorkshop(list, workshop) { 
    var index = list.indexOf(workshop); 

    if(index >= 0) { 
    list.splice(index, 1); 
    } 
} 

該函數期望每個數組都作爲參數傳入,並且會將其修改到位。在嵌套它們之前,如果將循環移出到函數中,事情總是會變得更加清晰和容易。

應該沒有理由不在這裏使用indexOf方法,因爲它可以節省您不必編寫額外的循環。但是,如果由於某種原因需要使用WorkshopId屬性在列表中找到該項目,則可以創建另一個輔助方法來爲您執行此操作。

function findWorkshop(list, workshop) { 
    for(var i = 0; i < list.length; i++) { 
    if(list[i].WorkshopId === workshop.WorkshopID) { 
     return i; 
    } 
    } 

    return -1; 
} 

然後,您只需修改removeWorkshop函數以反映這一點。

function removeWorkshop(list, workshop) { 
    var index = findWorkshop(list, workshop); 
    list.splice(index, 1); 
} 
+0

這正是我正在尋找的。我唯一的問題是,添加時,它似乎跳過了刪除'workshop'數組中的'oranges'對象,而是刪除'pineapples'。我試圖找出原因。任何見解? Codepen:http://codepen.io/trueScript/pen/GgVWMx – angularPrism

+1

啊。我的錯。原來'.splice'認爲負指數是相對於最後的。我會更新答案。 –

+1

可能需要改變的另一件事是,如果您要在文件中定義工作室對象,那麼您將需要'findWorkshop'函數而不是使用'indexOf'。 –

0
addRemoveWorkshops = function(){ 
var numberOfWorkshops = selectedWorkshops.length; 
for(var i = 0; i < numberOfWorkshops; i++){ 
    registeredWorkshops.push(selectedWorkshops[i]); 
    for(var j = 0, arrayLength = workshops.length; j < arrayLength; j++) { 
     var searchTerm = selectedWorkshops[i].WorkshopId; 
     if (workshops[j].WorkshopId === searchTerm) { 
      workshops = workshops.splice(j,1); 
     } 
    } 
    selectedWorkshops = selectedWorkshops.splice(i,1); 
} 

};

1

一個while環+一個for之一:

var workshops = [{ 
    name: 'apples', 
    WorkshopId: '19' 
}, { 
    name: 'oranges', 
    WorkshopId: '3b' 
}, { 
    name: 'pears', 
    WorkshopId: 'x6' 
}, { 
    name: 'pineapples', 
    WorkshopId: '55' 
}, { 
    name: 'watermelons', 
    WorkshopId: '8v' 
}]; 

var selectedWorkshops = [{ 
    name: 'oranges', 
    WorkshopId: '3b' 
}, { 
    name: 'watermelons', 
    WorkshopId: '8v' 
}, { 
    name: 'pears', 
    WorkshopId: 'x6' 
}]; 

var registeredWorkshops = []; 
var numberOfWorkshops; 

addRemoveWorkshops = function() { 
    numberOfWorkshops = selectedWorkshops.length; 
    // A single while statment is enough and lighter 
    while (selectedWorkshops.length) { 
     var removedWorkshop; 
     numberOfWorkshops = registeredWorkshops.push(selectedWorkshops[0]); 
     for (var i = 0; i < workshops.length; i++) 
     if (workshops[i].WorkshopId == selectedWorkshops[0].WorkshopId) { 
      workshops.splice(i, 1); 
      break; 
     } 
     selectedWorkshops.splice(0, 1); 
    } 
}; 
addRemoveWorkshops(); 

// Better for viewing the content (in firefox I have just "Object") : 
console.log("workshops : "); 
for (var i = 0; i < workshops.length; i++) 
console.log('- ' + workshops[i].name); 

console.log("selectedWorkshops : "); 
for (var i = 0; i < selectedWorkshops.length; i++) 
console.log('- ' + selectedWorkshops[i].name); 

console.log("registeredWorkshops : "); 
for (var i = 0; i < registeredWorkshops.length; i++) 
console.log('- ' + registeredWorkshops[i].name); 
+0

當我運行這個,它成功地刪除了'selectedWorkshops'數組中的對象。但是,它沒有成功從「工作室陣列」中刪除正確的項目。相反,其餘的數組項目是「蘋果」和「橙子」,儘管在註冊的工作室陣列中也可以找到橙子。 如果可以,請修改您的問題以解決此問題。除了它沒有工作,它是直接回答我的問題的最接近的東西。 – angularPrism

+1

我的不好,得到它... indexOf正在嚴格平等。來自研討會和選定的工作坊的桔子不是同一個對象,而是相同的。對不起,這個錯誤。我正在寫一個快速修復。 – Amessihel

+1

@saestris:已更新。無論如何,正如@Dan Prince所說的那樣,最好是細化你的數據結構:如果你不能遵循他的建議,我建議你這樣做:不應該在'selectedWorkshops'中存儲選定對象的克隆,而應該引用參考。例如:'selectedWorkshops.push(workshop [2])''。或寫一個函數:'selectedWorkshops.push(getWorkshopById('8v')); ' – Amessihel

2

我認爲這將是更容易略微重新考慮你的數據結構。如果您採用上面的強制性解決方案,則會出現在多個列表中出現重複值的風險。

registeredselected屬性添加到您的工作室對象會不會更容易?

var workshops = [ 
    { 
    name: 'apples', 
    WorkshopId: '19', 
    registered: true, 
    selected: false 
    }, 
    { 
    name: 'oranges', 
    WorkshopId: '3b', 
    selected: true, 
    registered: false 
    }, 
    // ... 
]; 

然後,如果您需要能夠獲得所有註冊研討會的列表,您可以使用過濾器創建它。

// helper function for filtering based 
// on a given property 
function property(name) { 
    return function(object) { 
    return object[name]; 
    } 
} 

var registered = workshops.filter(property('registered')); 
var selected = workshops.filter(property('selected')); 

要選擇一個車間,所有你需要做的是改變選擇屬性爲true:

workshops[3].selected = true; 

然後你可以寫原有功能進行註冊選擇這樣,所有的車間:

function registration(workshops) { 
    workshops.forEach(function(workshop) { 
    if(workshop.selected) { 
     workshop.registered = true; 
     workshop.selected = false; 
    } 
    }); 
} 
+0

不幸的是,在這種情況下我不能這樣做(儘管它肯定會更容易)。謝謝,不過。好答案。 – angularPrism

相關問題