使用另一个数组

时间:2018-04-05 15:49:37

标签: javascript arrays object prototype



Array.prototype.remove = function() {
  var what, a = arguments,
    L = a.length,
    ax;
  while (L && this.length) {
    what = a[--L];
    while ((ax = this.indexOf(what)) !== -1) {
      this.splice(ax, 1);
    }
  }
  return this;
};

var items = [{
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}]

var datesToRemove = [{
  title: 'Bokningsbar',
  start: moment("2018-04-06 06:00"),
  end: moment("2018-04-06 07:00"),
  allDay: false
}];
console.log("Before: " + items.length)
for (var i = 0; i < datesToRemove.length; i++) {
  items.remove(moment(datesToRemove[i].start).format("YYYY-MM-DD HH:mm"));
}
console.log("After: " + items.length)
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.0/moment.js"></script>
&#13;
&#13;
&#13;

我想使用另一个数组作为参考从一个数组中删除对象。两个数组只包含下面的对象。应在datesToRemove数组中删除items中的所有相应对象。我认为我可以使用的属性是start。不幸的是,没有Id

到目前为止,这是我的代码:

对象看起来像这样:

   var item = {
                            title: 'Bokningsbar',
                            start: moment(datesValue + " " + hourValue.start),
                            end: moment(datesValue + " " + hourValue.end),
                            allDay: false
                        };

Prototype.remove

       Array.prototype.remove = function () {
        var what, a = arguments,
            L = a.length,
            ax;
        while (L && this.length) {
            what = a[--L];
            while ((ax = this.indexOf(what)) !== -1) {
                this.splice(ax, 1);
            }
        }
        return this;
    };

用例:

  for (var i = 0; i < datesToRemove.length; i++) {
                            items.remove(moment(datesToRemove[i].start).format("YYYY-MM-DD HH:mm"));
                        }

通过此设置,我收到错误Cannot read property 'indexOf' of undefined。并删除所有athe obects。这也是一个不起作用的例子。但也许它说明了我想要的东西。如果有人对如何删除对象有更好的建议,请随时提出建议。

非常感谢所有帮助。

2 个答案:

答案 0 :(得分:2)

据我了解,remove期望(精确)相同的元素,并且通常在复杂元素上效果不佳。

我建议使用Array.prototype.filter

var items = [{
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar',
  start: moment("2018-04-05 06:00"),
  end: moment("2018-04-05 07:00"),
  allDay: false
}, {
  title: 'Bokningsbar to remove',
  start: moment("2018-04-06 06:00"),
  end: moment("2018-04-06 07:00"),
  allDay: false
}]

var datesToRemove = [{
  title: 'Bokningsbar',
  start: moment("2018-04-06 06:00"),
  end: moment("2018-04-06 07:00"),
  allDay: false
}];

for (var i = 0; i < datesToRemove.length; i++) {
  var toRemove = datesToRemove[i];
  items = items.filter(function(element) {
    return element.start.valueOf() != toRemove.start.valueOf();
  });
}

console.log(items);
<script src="https://momentjs.com/downloads/moment-with-locales.min.js"></script>

答案 1 :(得分:1)

无需扩展原生Array原型即可完成此操作。有一些方法可以处理Array操作,这些方法本身已经可用于JavaScript,可以解决您的问题。更重要的是,继续使用自定义Array方法与for循环一起使用解决方案可能非常容易产生意外/无意的负面影响,从而限制此解决方案可以扩展到应用程序中以供将来使用的程度。最明显的潜在缺陷是改变原始数据结构,极大地限制了可重用性,并且难以轻松准确地调试应用程序堆栈中导致的问题。这些原生Array方法将保持原始数据结构的完整性,在操作期间创建Array实例的浅表副本,并将它们作为最终结果返回。作为额外的奖励,这些方法可以根据您的需要以多种方式链接在一起。

  • .map()
  • .filter()
  • .reduce()

通常使用的另一种Array操作方法是.forEach().forEach()方法消除了必须编写和维护凌乱的for循环的麻烦;使整个代码库更容易阅读,更容易逻辑地遵循。但是,与先前列出的3个.forEach()操作方法不同,Array不能防止改变所使用的任何原始数据结构。它可以包含在您可以使用提到的其他Array方法创建的链中。但是,一旦被调用,.forEach()就会破坏链接方法的能力。

.map().filter().reduce()Array的迭代和操作提供了一种纯粹的,功能性的方法。虽然所有3种方法仍然提供循环Array的方法,但每种方法都提供了它自己独特的功能和操作目的。首先理解每种方法的独特用法对于理解何时以及如何有效地将它们链接在一起至关重要。

.MAP()

  • .map():与.forEach()类似,此方法会循环显示给定Array中的每个项目。当循环遍历每个项目的索引时,各个项目将针对提供的操作方法运行。最终结果是一个新的Array,每个项目都是循环期间提供的转换函数的产物。使用.map()记住的重要注意事项是,循环完成后返回的新Array始终与使用的原始Array长度相同。这使得.map()成为一个很好的选择,当您需要返回一个新的Array,其中的项目值与原始Array及其所有项目进行比较时反映了所需的转化值。

示例:

const originalArr = [1, 2, 3, 4, 5]

const incrementedArr = 
  originalArr.map(
    (n,i,arr) => {
      return n + 4
    }
  )

console.log(originalArr)     // console output => [1, 2, 3, 4, 5]
console.log(incrementedArr)  // console output => [5, 6, 7, 8, 9]

在上面的示例中,incrementedArr常量可以更简洁的方式重写。为了彻底回答你的问题,我详细地写了这篇文章,以说明一个要记住的重要注意事项。 .map().filter().reduce()默认提供三个参数。 .map().filter()的3个参数是相同的。他们是:

  1. 项目

      

    在循环迭代的每个索引处找到的单个项值

  2. 索引

      

    循环迭代期间找到的每个项目的索引值

  3. 数组

      

    提供对循环使用的原始数组的引用

  4. 也就是说,以上示例中的.map()更为简洁:

    const originalArr = [1, 2, 3, 4, 5]
    const incrementedArr = originalArr.map(n => n + 4)
    
    console.log(originalArr)     // console output => [1, 2, 3, 4, 5]
    console.log(incrementedArr)  // console output => [5, 6, 7, 8, 9]  
    

    .FILTER()

    • .filter():同样,与.forEach()一样,此方法会循环显示给定Array中的每个项目。与此同时,它会将Array中每个项目的值与提供的条件检查进行比较,为true中每个索引的每个项目返回falseArray 。最终输出将是Array个项目,其值全部返回为Boolean,可以是truefalse,具体取决于所提供的条件检查。这使得.filter()成为您需要返回新Array时的完美选择,而Array可能需要与提供的原始Array不同。换句话说,返回的新Array是用于过滤原始const originalArr = [1, 2, 3, 4, 5] const noEvenNumbersArr = originalArr.filter(n => n%2) console.log(originalArr) // console output => [1, 2, 3, 4, 5] console.log(noEvenNumbersArr) // console output => [1, 3, 5] 中不再需要的项值的条件检查的直接反映。

    示例:

    .reduce()

    <强>。降低()

    Array方法与提到的其他Array方法一样,遍历给定.map()中的所有项目。它的参数参数与.filter().map()不同。此外,虽然.filter()Array总是返回.reduce(),但Object提供了返回和.reduce()的功能。与所讨论的其他两种方法相比,.map()需要更多时间来正确解释。此外,使用我们使用.filter()// The Array "items" contains values that need to be removed. const items = [ { title: 'Bokningsbar', start: moment("2018-04-05 06:00"), end: moment("2018-04-05 07:00"), allDay: false }, { title: 'Bokningsbar', start: moment("2018-04-05 06:00"), end: moment("2018-04-05 07:00"), allDay: false }, { title: 'Bokningsbar', start: moment("2018-04-05 06:00"), end: moment("2018-04-05 07:00"), allDay: false }, { title: 'Bokningsbar', start: moment("2018-04-05 06:00"), end: moment("2018-04-05 07:00"), allDay: false } ] // The Array "datesToRemove" contains values that match what needs // to be removed from the"items" Array const datesToRemove = [ { title: 'Bokningsbar', start: moment("2018-04-05 06:00"), end: moment("2018-04-05 07:00"), allDay: false } ] 讨论的内容,可以形成一个解决方案来正确解决最初提出的问题。

    THE SOULTION

    .filter()

    Object方法可以处理解决问题所需的一切......几乎。问题现在围绕着两件具体的事情,  1.不对另一个项目数组过滤项目数组。相反,您正在尝试过滤另一个OBJECTS数组的OBJECTS数组。如果这是此意图,您可以修改以下内容以检查本地Object.keys()方法(和迭代器),例如Object.values() const mergeUniqueMatches = (catArr) => catArr.filter((elem, pos, arr) => arr.indexOf(elem) == pos) const mergedArr = mergeUniqueMatches(items.concat(datesToRemove))

    mergedArr

    Array记录到控制台会显示新的mergedArr。原始数据仍然完全不受影响。同样,浅拷贝是我们在这里使用的。

    现在的诀窍是&#34; Dedupe&#34; const dedupedArr = [...new Set(mergedArr)] 。幸运的是,ES6 / 7让这件事变得轻而易举。试试:

    items

    进一步移动虽然需要一些澄清。通过随时提供密钥(如生成的uuid)并Array对象添加到datesToRemove,您可以更轻松地使自己变得更容易。然后在该项目移至Array .filter()之后,您需要做的就是从实例ID密钥(uuid)中 const destructingOptionWithES6 = { ...items, ...datesToRemove } const ideallyAllYouShouldHaveToDoIsThisFunction = items.filter(val => !datesToRemove.includes(val)) 安全删除正确的项目,而不必担心变异沿途的任何数据。

    我将给你留下这两个最终的选择,

    {{1}}