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

时间:2022-01-11 07:53:42

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'). Third, I have a final array called 'registeredWorkshops'.

我正在尝试构建一个三层函数:首先,数组列出可用的研习班(数组称为“研习班”)。第二,另一个数组列出用户已选择的研讨会(这个数组称为“selectedworkshop”)。第三,我有一个名为“registeredworkshop”的最终数组。

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'. So, where those objects used to exist in both 'selectedworkshops' and 'workshops', now they only exist in 'registeredWorkshops'.

当我的函数运行时,我希望“selectedworkshop”中的对象被添加到“registeredworkshop”中,然后我希望从“selectedworkshop”和“workshop”中的任何匹配元素中删除“selectedworkshop”中的任何对象。因此,这些对象曾经同时存在于“selectedworkshop”和“workshop”中,现在它们只存在于“registeredworkshop”中。

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?

但是,这个函数似乎不能正常工作。它似乎并没有删除正确的研讨会,而且它似乎只是向注册研讨会添加了一个selectedworkshop。我做错了什么?

Here's a codepen demonstration: http://codepen.io/trueScript/pen/GgVWMx

这里有一个代码页演示:http://codepen.io/trueScript/pen/GgVWMx

4 个解决方案

#1


2  

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. 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.

这里应该没有理由不使用indexOf方法,因为这样可以避免您不得不编写额外的循环。但是,如果出于某种原因,您需要使用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);
}

#2


2  

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?

将注册的和选择的属性添加到您的workshop对象是否会更容易?

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:

要选择一个workshop,您需要做的就是将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;
    }
  });
}

#3


1  

A while loop + a for one :

A while循环+ A for one:

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

#4


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


2  

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. 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.

这里应该没有理由不使用indexOf方法,因为这样可以避免您不得不编写额外的循环。但是,如果出于某种原因,您需要使用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);
}

#2


2  

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?

将注册的和选择的属性添加到您的workshop对象是否会更容易?

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:

要选择一个workshop,您需要做的就是将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;
    }
  });
}

#3


1  

A while loop + a for one :

A while循环+ A for one:

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

#4


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

};

};