在Index as Array Lengthens处插入元素

时间:2018-01-25 21:18:08

标签: javascript arrays ecmascript-6

假设我有一组对象var schedule

我正在循环forEach,通过比较当前元素的结束时间和下一个元素的开始时间来检查给定日期的此计划中是否存在间隙。如果它们不一样,那么时间表上肯定存在差距。

到目前为止这一切都有效。问题在于将“STUFF”拼接在正确的索引处。目前发生的是...对于我拼接的每次迭代,列表长度增加1,因此[[魔法索引]]当前没有拼接到正确的索引。 (还没那么神奇)。

var schedule = [{s: "9:00 AM", e: "10:00 AM"}, {s: "11:00 AM", e: "12:00 PM"}, {s: "12:00 PM", e: "2:00 PM"}, {s: "5:00 PM", e: "7:00 PM"}]

schedule.forEach((element, index) => { 
         if(index+1 <= schedule.length -1){
              var nextElement= schedule[index+1]; 
              if( !element.e.isSame(nextElement.s)){
                    //PSEDUO CODE
                    schedule.splice([[magical index]], 0, "STUFF");
              };
         };  
    }

所需的输出/结果将如下所示......在原始计划数组中插入“STUFF” var schedule = [{s: "9:00 AM", e: "10:00 AM"}, "STUFF", {s: "11:00 AM", e: "12:00 PM"}, {s: "12:00 PM", e: "2:00 PM"}, "STUFF", {s: "5:00 PM", e: "7:00 PM"}]

5 个答案:

答案 0 :(得分:2)

非常简单易懂的解决方案。希望它有所帮助。

&#13;
&#13;
var schedule = [{s: "9:00 AM", e: "10:00 AM"}, {s: "11:00 AM", e: "12:00 PM"}, {s: "12:00 PM", e: "2:00 PM"}, {s: "5:00 PM", e: "7:00 PM"}]
var newSchedule =[]; //new array that will contains the result 
const leng = schedule.length ;

schedule.forEach((element, index) => { 
  newSchedule.push(schedule[index]); //always add the schedule elements
  if(index+1 <= leng-1 ){
      var nextElement= schedule[index +1]; 
      if( element.e !== nextElement.s){
            newSchedule.push("STUFF"); //push the string "STUFF" if there is difference.
      };
      
  };  
});

console.log(newSchedule);
&#13;
&#13;
&#13;

答案 1 :(得分:1)

在不深入实施的情况下,我可以通过“插入循环”问题告诉您一直对我有用的东西:

从头到尾循环

当您更改当前索引数据时,您不需要关心数组的长度或后续数据,这会受到插入当前索引的影响。

不幸的是forEach方法没有提供它。

幸运的是,基于原始文件编写自己的文章并不难:

Array.prototype.forEach2 = function(fun /*, thisp*/) {
    var len = this.length >>> 0;
    if (typeof fun != "function") {
        throw new TypeError();
    }

    var thisp = arguments[1];
    for (var i = len - 1; i >= 0; i--) {
    	fun.call(thisp, this[i], i, this);
    }
};
var schedule = [
	{s: "9:00 AM", e: "10:00 AM"}, 
  {s: "11:00 AM", e: "12:00 PM"}, 
  {s: "12:00 PM", e: "2:00 PM"}, 
  {s: "5:00 PM", e: "7:00 PM"}
];

schedule.forEach2(function(element, index) { 
    var nextElement= schedule[index-1]; 
		if( nextElement && element.s !== nextElement.e){
        schedule.splice(index, 0, "STUFF");
    };
});
    
console.log(schedule);

编辑:注意,你需要反转函数内部的逻辑,否则它将无法正常运行。但是,使用此解决方案,您不会引入第二个数组变量,这使得使用更大的大小变得有趣。

答案 2 :(得分:1)

您可以在简单的for循环中执行此操作:

var schedule = [{s: "9:00 AM", e: "10:00 AM"}, {s: "11:00 AM", e: "12:00 PM"}, {s: "12:00 PM", e: "2:00 PM"}, {s: "5:00 PM", e: "7:00 PM"}];

for (let i = 0; i < schedule.length; i++)
  if (schedule[i+1] && schedule[i].e !== schedule[i+1].s)
    schedule.splice(++i, 0, "STUFF");

console.log(schedule);

答案 3 :(得分:1)

略有不同的方法:

&#13;
&#13;
var schedule = [{s: "9:00 AM", e: "10:00 AM"}, {s: "11:00 AM", e: "12:00 PM"},
                {s: "12:00 PM", e: "2:00 PM"}, {s: "5:00 PM", e: "7:00 PM"}]

const insertStuff = sched => sched.reduce((all, curr, idx) => 
  ((idx > 0 && curr.s !== sched[idx - 1].e) ? all.concat('STUFF') : all).concat(curr)
, [])

console.log(insertStuff(schedule))
&#13;
&#13;
&#13;

这个技术使用与Firas Omrane的答案相同的技巧。但它将其转换为可重用的函数,并使用reduce而不是显式循环。

我不知道您的数据,但我可以想象,如果时间可以重叠,则需要稍微延长,但您仍想报告差距。这个版本使用了非常不雅的timeCompare,但效果与上面的相似:

&#13;
&#13;
const timeCompare = (t1, t2) => {
  const [time1, meridian1] = t1.split(/\s/g);
  const [h1, m1] = time1.split(':').map(Number)
  const [time2, meridian2] = t2.split(/\s/g);
  const [h2, m2] = time2.split(':').map(Number)
  return (meridian1 === meridian2) 
     ? (h1 === h2) 
       ? (m1 === m2) ? 0 : (m1 < m2) ? -1 : 1 
       : (h1 < h2) ? -1 : 1 
     : (meridian1 === "AM") ? -1 : 1
}

const overlapped = [{s: "9:00 AM", e: "11:30 AM"}, {s: "11:00 AM", e: "12:00 PM"}, 
                    {s: "1:30 PM", e: "2:00 PM"}, {s: "5:00 PM", e: "7:00 PM"}]

const insertGap = sched => sched.reduce((all, curr, idx) => 
  (idx > 0 && timeCompare(curr.s,  sched[idx - 1].e) > 0) ? all.concat('GAP').concat(curr) : all.concat(curr)
, [])

console.log(insertGap(overlapped))
&#13;
&#13;
&#13;

答案 4 :(得分:0)

我建议你这样做,不要改变数组。 Splice是javascript中最糟糕的功能之一,比它的价值更令人头疼。我一直在制作中使用这个功能:

function addToArray(arr, item, i) {
  i === 0 ? i = 0 : i = i || arr.length;
  const arr1 = arr.slice(0, i);
  const arr2 = arr.slice(i);
  return arr1.concat([item].concat(arr2));
}

i是一个可选参数。如果省略,则将项放在最后,否则通过切片到该索引并从该索引将其放入指定的索引中,然后将数组与两个中间的所需插入一起连接。

因此,在您的循环中,一旦您的条件变为真,您可以使用当前索引+ 1作为i来调用上述函数。如果您的清单是

[{s: "9:00 AM",  e: "10:00 AM"}, 
 {s: "11:00 AM", e: "12:00 PM"}, 
 {s: "12:00 PM", e: "2:00 PM"},
 {s: "5:00 PM",  e: "7:00 PM"}]

你想在第二项之后添加一个项目:

schedule = addToArray(schedule, "GAP", index + 1)
//where index is 1

导致

[{s: "9:00 AM",  e: "10:00 AM"}, 
 {s: "11:00 AM", e: "12:00 PM"}, 
 "GAP",
 {s: "12:00 PM", e: "2:00 PM"},
 {s: "5:00 PM",  e: "7:00 PM"}]

希望有意义!