简体   繁体   English

如何使用 ES6 在 javascript 中删除或添加项目到锯齿状数组?

[英]How to remove or add an item to a jagged array in javascript using ES6?

Say I have the following jagged array假设我有以下锯齿状数组

var data = [
            ['a','b','c'],
            ['d','e',['f','g']],
            ['h','i','j']
          ];

and I want to be able to remove 'f' so that result is going to look like我希望能够删除 'f' 以便结果看起来像

var data1 = [
            ['a','b','c'],
            ['d','e',['g']],
            ['h','i','j']
          ];

Similarly I want to add 'f' after 'h' in the array above to give me同样,我想在上面的数组中的 'h' 之后添加 'f' 来给我

var data2 = [
            ['a','b','c'],
            ['d','e',['g']],
            ['h','f','i','j']
          ];

how can I achieve this in javascript or ES6?我怎样才能在 javascript 或 ES6 中实现这一点? please note my jagged arrays can be multiple level deep the above just serves as an example.请注意,我的锯齿状数组可以是多级深度,以上仅作为示例。

so I need functions like data.remove('f') to result in data1 data1.addafter('h','f') to result in data2所以我需要像data.remove('f')这样的函数来生成 data1 data1.addafter('h','f')来生成 data2

I tried a recursive function like below but unable to crack it...我尝试了一个像下面这样的递归函数,但无法破解它......

function arrmap([head, ...tail], fn) {   
    return tail.length === 0 ? [fn(head)] : [fn(head), ...map(tail, fn)];  
}

You need a recursive combination of map and filter.您需要映射和过滤器的递归组合。 In this case, I would just go with a recursive function with a for...of loop:在这种情况下,我只会使用带有for...of循环的递归函数:

 const fn = arr => { const r = [] for(const item of arr) { if(Array.isArray(item)) r.push(fn(item)) else if(item === 'h') r.push('h', 'f') else if(item !== 'f') r.push(item) } return r; } const data = [['a','b','c'],['d','e',['f','g']],['h','i','j']] const result = fn(data) console.log(result)

If you need a more generic approach, you can extract fn :如果您需要更通用的方法,可以提取fn

 const nestedMap = (arr, fn) => arr.reduce((r, item) => { const val = Array.isArray(item) ? [nestedMap(item, fn)] : fn(item) return val !== undefined ? r.concat(val) : r }, []) const data = [['a','b','c'],['d','e',['f','g']],['h','i','j']] const result = nestedMap(data, item => { if (item === 'h') return ['h', 'f'] if (item !== 'f') return item }) console.log(result)

I am not adding much to Ori's original solution, but, you can also utilize closures with the same generic approach Ori mentioned:我没有为 Ori 的原始解决方案添加太多内容,但是,您也可以使用 Ori 提到的相同通用方法使用闭包:

 const nestedMap = (fn) => (arr) => { const r = [] for(const item of arr) { if(Array.isArray(item)) r.push(nestedMap(fn)(item)) else { const val = fn(item) if (val) r.push(...val) } } return r; } const data = [['a','b','c'],['d','e',['f','g']],['h','i','j']] const addAfter = nestedMap((item) => { if (item === 'h') return ['h', 'f'] if (item !== 'f') return [item] }); const remove = nestedMap((item) => { if (item === 'f') return [] return [item]; }); console.log(addAfter(data)); console.log(remove(data));

We use object-scan for data processing tasks like this.我们使用对象扫描来处理这样的数据处理任务。 It's very powerful once you wrap your head around how to use it.一旦你了解如何使用它,它就会非常强大。 Here is how you'd solve your questions这是您解决问题的方法

 // const objectScan = require('object-scan'); const rm = (v, input) => objectScan(['**[*]'], { abort: true, rtn: 'bool', filterFn: ({ value, parent, property }) => { if (value === v) { parent.splice(property, 1); return true; } return false; } })(input); const ins = (after, v, input) => objectScan(['**[*]'], { abort: true, rtn: 'bool', filterFn: ({ value, parent, property }) => { if (value === after) { parent.splice(property + 1, 0, v); return true; } return false; } })(input); const data = [ ['a', 'b', 'c'], ['d', 'e', ['f', 'g']], ['h', 'i', 'j'] ]; console.log(rm('f', data)); // => true console.log(rm('f', data)); // already removed // => false console.log(data); // => [ [ 'a', 'b', 'c' ], [ 'd', 'e', [ 'g' ] ], [ 'h', 'i', 'j' ] ] console.log(ins('x', 'f', data)); // can not find 'x' // => false console.log(ins('h', 'f', data)); // => true console.log(data); // => [ [ 'a', 'b', 'c' ], [ 'd', 'e', [ 'g' ] ], [ 'h', 'f', 'i', 'j' ] ]
 .as-console-wrapper {max-height: 100% !important; top: 0}
 <script src="https://bundle.run/object-scan@13.8.0"></script>

Disclaimer : I'm the author of object-scan免责声明:我是对象扫描的作者

As this was brought back up, and the current solutions seem more complex than necessary, here's an approach using flatMap for each:由于这被重新提出,并且当前的解决方案似乎比必要的更复杂,这里有一种对每个解决方案使用flatMap的方法:

 const removeVal = (val, xs) => xs .flatMap ((x) => x == val ? [] : Array.isArray(x) ? [removeVal (val, x)] : [x]) const addAfter = (prev, val, xs) => xs .flatMap ((x) => x == prev ? [x, val] : Array.isArray(x) ? [addAfter (prev, val, x)] : [x]) const data = [['a','b','c'], ['d','e',['f','g']], ['h','i','j']] const data1 = removeVal ('f', data) const data2 = addAfter ('h', 'f', data1) console .log ('original', data) console .log ('after removal', data1) console .log ('after add', data2) console .log ('original', data) // unchanged
 .as-console-wrapper {max-height: 100% !important; top: 0}

As demonstrated, these do not change your input structure, but create parallel ones with the changes applied.正如所演示的,这些不会改变您的输入结构,而是创建应用更改的并行结构。

Note that these remove every 'f' and adds one after every 'h' .请注意,这些删除每个'f'并在每个'h'后添加一个。 This shouldn't be a problem given the stated requirements, but it could be an issue in some circumstances.鉴于规定的要求,这应该不是问题,但在某些情况下可能会成为问题。

OriDrori talked about a combination of map and filter . OriDrori 谈到了mapfilter的组合。 flatMap often makes that combination unnecessary. flatMap通常使这种组合变得不必要。 It can be a pretty powerful tool.它可以是一个非常强大的工具。

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

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