简体   繁体   English

将匹配的对象添加到另一个数组时,从数组中删除它们

[英]Remove Matching Objects from Array While Adding them to Another Array

I am trying to build a 3-tiered function: First, an array lists available workshops (array is called 'workshops'). 我正在尝试构建一个三层函数:首先,一个数组列出了可用的工作坊(该数组称为“车间”)。 Second, another array lists workshops that a user has selected (this array is called 'selectedWorkshops'). 其次,另一个数组列出了用户选择的工作坊(此数组称为“ selectedWorkshops”)。 Third, I have a final array called 'registeredWorkshops'. 第三,我有一个名为“ registeredWorkshops”的最终数组。

When my function is run, I want objects within 'selectedWorkshops' to be added to 'registeredWorkshops', then I want to delete any objects within 'selectedWorkshops' from both 'selectedWorkshops' and any matching elements from 'workshops'. 运行函数时,我希望将“ selectedWorkshops”中的对象添加到“ registeredWorkshops”中,然后要从“ selectedWorkshops”中删除“ selectedWorkshops”中的任何对象以及从“ workshops”中删除任何匹配的元素。 So, where those objects used to exist in both 'selectedworkshops' and 'workshops', now they only exist in 'registeredWorkshops'. 因此,以前那些对象既存在于“选定的车间”中又存在于“车间”中,现在它们仅存在于“注册的车间”中。

Here's what I've got so far: 到目前为止,这是我得到的:

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();

However, the function doesn't appear to work properly. 但是,该功能似乎无法正常工作。 It doesn't seem to be deleting the correct workshops, and it only seems to add one of the selectedWorkshops to registeredWorkshops. 它似乎并没有删除正确的工作室,而似乎只是将其中一个选定的车间添加到注册的车间中。 What am I doing wrong? 我究竟做错了什么?

Here's a codepen demonstration: http://codepen.io/trueScript/pen/GgVWMx 这是一个代码笔演示: http ://codepen.io/trueScript/pen/GgVWMx

I think it would be easier to slightly rethink your data structure. 我认为稍微重新考虑一下数据结构会比较容易。 If you go for the imperative solution above, you run this risk of ending up with duplicate values in more than one list. 如果您选择上述命令式解决方案,则可能会面临这样的风险,即最终在多个列表中出现重复的值。

Would it not be easier to add registered and selected properties to your workshop objects? registeredselected属性添加到您的车间对象会更容易吗?

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

Then if you need to be able to get a list of all the registered workshops, you can create it using a filter. 然后,如果需要获取所有已注册研讨会的列表,则可以使用过滤器创建它。

// 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'));

To select a workshop, all you need to do is change the select property to true: 要选择一个研讨会,您需要做的就是将select属性更改为true:

workshops[3].selected = true;

You could then write the original function to register all workshops that were selected like this: 然后,您可以编写原始功能来注册所有选择的研讨会,如下所示:

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

If it's not possible to add other properties to the objects (as per my other answer ) then I'd tackle it like this: 如果不可能向对象添加其他属性(按照我的其他回答 ),那么我将按照以下方式解决:

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);
  }
}

The function expects each of the arrays to be passed in as arguments and it will modify them in place. 该函数期望将每个数组作为参数传递,并将在适当位置对其进行修改。 Things always become clearer and easier to test if you move your loops out into functions before nesting them. 如果在嵌套之前将循环移到函数中,事情总是变得更加清晰和容易测试。

There should be no reason not to use the indexOf method here, as it saves you having to write an extra loop. 这里没有理由不使用indexOf方法,因为它省去了编写额外循环的麻烦。 However, if for some reason you needed to use the WorkshopId property to locate the item within the list, you could create another helper method to do this for you. 但是,如果由于某种原因需要使用WorkshopId属性在列表中定位该项目,则可以创建另一个帮助程序方法来为您执行此操作。

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

  return -1;
}

Then you just amend the removeWorkshop function to reflect that. 然后,您只需修改removeWorkshop函数即可反映出来。

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

A while loop + a for one : 一个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);
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);
}

}; };

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM