计算对象中值的更智能方法(JS,React)

时间:2016-10-08 18:47:18

标签: javascript arrays object reactjs

看一下下面的代码,是否有更好的方法来获取包含特定键/值对的项目在反应状态内的数量?

一旦我所经历的列表变得很大,这种方法似乎会导致瓶颈。

以下是手头问题的简化示例:



class App extends React.Component {
  constructor() {
    super();
    
    this.state = {
      animals: [
        {type: 'cat'},
        {type: 'dog'},
        {type: 'cat'},
      ]
    };
  }

  render() {
    return(
      <div className="app">
        <Categories state={this.state} />
      </div>
    );
  }
}

class Categories extends React.Component {
  constructor() {
    super();

    this.countItems = this.countItems.bind(this);
  }

  countItems(type) {
    var count = 0;
  
    for(var i = 0; i < this.props.state.animals.length; i++) {
      if(this.props.state.animals[i].type === type) {
        count++;
      }
    }
    
    return count;
  }

  render() {
    return(
      <div className="categories">
        <div>Total animals: {this.props.state.animals.length}</div>
        <div>Cats: {this.countItems('cat')}</div>
        <div>Dogs: {this.countItems('dog')}</div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById('container'));
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>

<div id="container"></div>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

如果你不改变你的州的结构,那么你必须做一些循环并按类型计算。

更具表现力的方法可能是使用reduce:

countItems(type) {  
    return this.props.state.animals.reduce((acc, next) => {
        return next.type == type ? acc + 1 : acc)
    }, 0);
  }

但是,如果性能有问题:

  1. 您可以将计数保持在状态,并在每次animals更改时计算一次

  2. 您可以将每种类型的动物分成一个单独的状态阵列,然后在每个动物上使用length

  3. 将状态更改为此类状态可能有所帮助:

  4. this.state = { animals: { dogs: [], cats: [] } }

答案 1 :(得分:1)

如果这是您经常调用的方法,那么按类型索引数据(动物)可能会很有用,并且每当您进行更改时都会保持更新。

例如:

App构造函数中,您将创建另一个属性animalsPerType

  constructor() {
    super();

    this.state = {
      animals: [
        {type: 'cat'},
        {type: 'dog'},
        {type: 'cat'},
      ]
    };
    this.state.animalsPerType = this.state.animals.reduce(function(acc, animal) {
        return acc.set(animal.type, (acc.get(animal.type) || []).concat(animal));
    }, new Map());
  }

然后您的countItems方法变得微不足道了:

  countItems(type) {
    return this.props.state.animalsPerType.get(type).length;
  }