如何合并线性数组的元素?

时间:2018-10-19 16:37:08

标签: javascript recursion

我的数据如下:

[ [ '0s', '0.200s' ],
  [ '0.200s', '0.600s' ],
  [ '1.600s', '2.500s' ],
  [ '3.500s', '3.900s' ],
  [ '3.900s', '4.400s' ],
  [ '4.400s', '4.600s' ],
  [ '4.600s', '4.700s' ],
  [ '4.700s', '5.200s' ],
  [ '5.200s', '5.400s' ],
  [ '5.400s', '5.800s' ],
  [ '5.800s', '6.100s' ],
  [ '6.100s', '6.800s' ],
  [ '6.800s', '7s' ],
  [ '7s', '7.300s' ],
  [ '7.300s', '7.500s' ]
]

第一个元素在0.200s处结束,这是第二个元素开始的地方。因此,我希望将这2个元素合并为['0s', '0.600s']

下一个元素不会在该元素结束的地方开始,因此应该继续。最终,结果应如下所示:

[ [ '0s', '0.600s' ],
  [ '1.600s', '2.500s' ],
  [ '3.500s', '7.500s' ]
]

我正在尝试递归地执行此操作,但是它给出了错误。这是我的功能:

function combineStartsEnds(timecodes) {
  if (timecodes[0][1] === timecodes[1][0]) {
    let combined = [
      [timecodes[0][0], timecodes[1][1]]
    ].concat(_.slice(timecodes, 2));

    return combineStartsEnds(combined);
  } else {
    return timecodes[0].concat(combineStartsEnds(_.slice(timecodes, 1)));
  }
};

这给出了一个错误:

TypeError: Cannot read property '0' of undefined

关于如何实现此目标的任何想法?

6 个答案:

答案 0 :(得分:4)

您在这里缺少括号,

 return timecodes[0].concat(...)

必须是:

 return [timecodes[0]].concat(...)

此外,您需要一个基本案例来结束递归:

 function combineStartsEnds(timecodes) {
   if(!timecodes.length) return [];

我该怎么做:

 function combineStartsEnds(timecodes) {
   const result = []; let previous = [];
   for(const [start, end] of timecodes) {
     if(start === previous[/*end*/ 1]) {
       previous[/*end*/ 1] = end;
     } else {
       result.push(previous = [start, end]);
    }
  }
  return result;
 }

答案 1 :(得分:1)

您也可以使用reduce进行此操作。

const times = [ [ '0s', '0.200s' ],
  [ '0.200s', '0.600s' ],
  [ '1.600s', '2.500s' ],
  [ '3.500s', '3.900s' ],
  [ '3.900s', '4.400s' ],
  [ '4.400s', '4.600s' ],
  [ '4.600s', '4.700s' ],
  [ '4.700s', '5.200s' ],
  [ '5.200s', '5.400s' ],
  [ '5.400s', '5.800s' ],
  [ '5.800s', '6.100s' ],
  [ '6.100s', '6.800s' ],
  [ '6.800s', '7s' ],
  [ '7s', '7.300s' ],
  [ '7.300s', '7.500s' ]
];

const merged = times.reduce((acc, [t3, t4]) => {
  const [t1, t2] = acc[acc.length - 1] || [null, null];
  if (t2 === t3) {
    acc.pop();
    acc.push([t1, t4]);
  } else {
    acc.push([t3, t4]);
  }
  return acc;
}, []);

console.log(merged);

答案 2 :(得分:1)

您也可以尝试以下方法来获得所需的结果。

(1)展平数组,您将得到

arr.flat()

["0s", "0.200s", "0.200s", "0.600s", "1.600s", "2.500s", "3.500s", "3.900s", "3.900s", "4.400s", "4.400s", "4.600s", "4.600s", "4.700s", "4.700s", "5.200s", "5.200s", "5.400s", "5.400s", "5.800s", "5.800s", "6.100s", "6.100s", "6.800s", "6.800s", "7s", "7s", "7.300s", "7.300s", "7.500s"]

(2)过滤并删除元素,如果元素在其前后存在,您将得到

arr.flat().filter((d,i,c) => d != c[i-1] && d != c[i+1])

["0s", "0.600s", "1.600s", "2.500s", "3.500s", "7.500s"]

(3)将以上结果简化为所需的格式

arr.flat()
    .filter((d,i,c) => d != c[i-1] && d != c[i+1])
    .reduce((res, d, i, c) => (i%2 == 0 && res.push([d, c[i+1]]) , res) , [])

[["0s", "0.600s"]
["1.600s", "2.500s"]
["3.500s", "7.500s"]]

答案 3 :(得分:1)

如何使用const data = [ ['0s', '0.200s'], ['0.200s', '0.600s'], ['1.600s', '2.500s'], ['3.500s', '3.900s'], ['3.900s', '4.400s'], ['4.400s', '4.600s'], ['4.600s', '4.700s'], ['4.700s', '5.200s'], ['5.200s', '5.400s'], ['5.400s', '5.800s'], ['5.800s', '6.100s'], ['6.100s', '6.800s'], ['6.800s', '7s'], ['7s', '7.300s'], ['7.300s', '7.500s'] ]; var data_map = new Map(data); for (var [key, value] of data_map) { while (data_map.has(value)) { var new_value = data_map.get(value); data_map.set(key, new_value); data_map.delete(value); value = new_value; } } data_map.forEach((value, key) => console.log(`[${key}, ${value}]`));

{{1}}

答案 4 :(得分:0)

您可以通过检查值来单循环减少数组,并更新最后一个数组或将新数组推送到结果集中。

var data = [['0s', '0.200s'], ['0.200s', '0.600s'], ['1.600s', '2.500s'], ['3.500s', '3.900s'], ['3.900s', '4.400s'], ['4.400s', '4.600s'], ['4.600s', '4.700s'], ['4.700s', '5.200s'], ['5.200s', '5.400s'], ['5.400s', '5.800s'], ['5.800s', '6.100s'], ['6.100s', '6.800s'], ['6.800s', '7s'], ['7s', '7.300s'], ['7.300s', '7.500s']],
    combined = data.reduce((r, [a, b]) => {
        var last = r[r.length - 1];
        if (last && a === last[1]) {
            last[1] = b;
        } else {
            r.push([a, b]);
        }
        return r;
    }, []);
    
console.log(combined);
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 5 :(得分:0)

使用递归的一种方法–

const start = ([ a, b ]) =>
  a

const end = ([ a, b ]) =>
  b

const join = ([ a, b, ...rest ]) =>
  // base: no `a`
  a === undefined
    ? []
  // inductive: some `a`  
  : b === undefined
    ? [ a ]
  // inductive: some `a` and some `b` (joinable)
  : end (a) === start (b)
    ? join ([ [ start (a), end (b) ], ...rest ])
  // inductive: some `a` and some `b` (non-joinable)
  : [ a, ...join ([ b, ...rest ]) ]

const data =
  [ [ '0s', '0.200s' ]
  , [ '0.200s', '0.600s' ]
  , [ '1.600s', '2.500s' ]
  , [ '3.500s', '3.900s' ]
  , [ '3.900s', '4.400s' ]
  , [ '4.400s', '4.600s' ]
  , [ '4.600s', '4.700s' ]
  , [ '4.700s', '5.200s' ]
  , [ '5.200s', '5.400s' ]
  , [ '5.400s', '5.800s' ]
  , [ '5.800s', '6.100s' ]
  , [ '6.100s', '6.800s' ]
  , [ '6.800s', '7s' ]
  , [ '7s', '7.300s' ]
  , [ '7.300s', '7.500s' ]
  ]

console.log (join (data))
// [ [ '0s', '0.600s' ]
// , [ '1.600s', '2.500s' ]
// , [ '3.500s', '7.500s' ]
// ]