在Ramda中获取给定元素在二维数组中的位置

时间:2017-02-13 16:11:10

标签: javascript ramda.js

我有一个包含一些数据的数组,即

const data = [[   , '+',    ],
              ['+',    , '+'],
              [   ,    , '+']]

我想获得每个元素的[x,y]坐标为'+':

const expected = [[1, 0], [0, 1], [2, 1], [2, 2]]

我怎么能在Ramda那样做?

我淘汰了一些有效的代码:

const getHorizontalPosition = R.map(R.addIndex(R.reduce)
  ( (xs, el, idx) => R.equals('+', el) ? R.append(idx, xs) : xs, [] ))

const combineWithVerticalPosition = R.addIndex(R.chain)
  ( (xs, y) => R.map( (x) => [x, y] )(xs) )

pipe(getHorizontalPosition,
     combineWithVerticalPosition)(data)

但是,正如你所看到的那样,它很丑陋而且不太可读。我怎样才能更优雅地做到这一点?

link to the code in ramda repl

4 个答案:

答案 0 :(得分:3)

正如您可能已经注意到的那样,Ramda对索引处理没有太大作用。我无法想出一个特别好的解决方案。

这样的东西会起作用,但在评论中提到的两个减速器似乎不那么优雅了:

pipe(addIndex(map)((xs, i) => pipe(
  map(equals('+')), 
  addIndex(map)((x, j) => x && [i, j]), 
  reject(equals(false))
)(xs)), unnest)(data)

您可以在 Ramda REPL

上看到这一点

答案 1 :(得分:1)

ES6的优雅之处在于。来到ES6后不需要Ramda。

const result= [];              
data.forEach((row, i) => 
   row.forEach((item, j) => item === '+' && result.push([i, j]))
)

另一种方式(没有突变+不使用varconstlet):

[].concat(...data.map((row, i) => row.map((item, j) => item === '+' ? [
        [i, j]
      ] : [])
      .filter(coord => coord.length)
     )
)



const data = [[   , '+',    ],
              ['+',    , '+'],
              [   ,    , '+']]
   
const result= [];              
data.forEach((row, i) => 
   row.forEach((item, j) => item === '+' && result.push([i, j]))
)
              
console.log(
  result             
 )        




答案 2 :(得分:1)

这是另外一种方法

const hasPlus = item => item == '+'
const notNull = item => item != null
const joinResults = (prev,next) => prev.concat(next);

const results = Array.from(data, (value2d, y) => {
  let indexOrNull = Array.from(value2d, (value1d, x) => hasPlus(value1d) ?  x : null);
  let indices = filter(notNull, indexOrNull);
  let indexed = map(x => [x, y] , indices);
  return indexed;
})

reduce(joinResults, [], results);

Ramda Snippet

答案 3 :(得分:0)

获取所有索引,然后将所有索引保留在元素等于'+'的位置。

const mapIndexed = R.addIndex(R.map)

const getIndexes = (xss) => 
  R.unnest(mapIndexed((xs, i) => mapIndexed((x, j) => [i, j], xs), xss))

const data = [[   , '+',    ],
              ['+',    , '+'],
              [   ,    , '+']]

const output = 
  R.filter(R.pathEq(R.__, '+', data), getIndexes(data))

console.log(output)
<script src="//cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>