在JavaScript ES6中寻找更有效的排序算法

时间:2018-10-27 23:59:37

标签: javascript algorithm sorting ecmascript-6

让我知道这是否不合适。

我目前正在使用带有不同标记(最多1000个)的地图构建一个React应用,每个地图都有其特定性。用户可以设置不同的过滤器,应用程序应显示相关的过滤器。我目前有一种有效的算法,但我敢肯定,我们可以提高它的效率,减少资源消耗。

这是我要讲的代码:

将仅显示重要内容。

要解释渲染,我有一个地图,其中显示了所有标记,下面有所有过滤器的列表,用户可以单击以应用该过滤器。

谢谢您的贡献!

class SomeComponent extends Component {
    state = {
        allMarkers: [
            {id: "1", filter: ['weekout', 'restaurant'], latlng: {latitude: 37.78825, longitude: -122.4224},title:'42'},
            {id: "2", filter: ['weekout'], latlng: {latitude: 37.78814, longitude: -122.4314},title:'Taverne du mont belon'},
            {id: "3", filter: ['restaurant', 'party'], latlng: {latitude: 37.78825, longitude: -122.1224},title:'Chez Lapin'},
            {id: "4", filter: ['party'], latlng: {latitude: 37.78825, longitude: -122.3324},title:'Pizza toto'},
            // up to 1000
        ],
        filteredMarkers: [
        ],
        filters: [
            {id: "1", selected: true, text: 'filter', filter: 'weekout'},
            {id: "2", selected: true, text: 'filter', filter:'pin'},
            {id: "3", selected: true, text: 'filter', filter: 'party'},
            {id: "4", selected: true, text: 'filter', filter: 'restaurant'},
            {id: "5", selected: false, text: 'filter', filter: 'beer'},
            {id: "6", selected: true, text: 'filter', filter:'love'},
            {id: "7", selected: false, text: 'filter', filter:'yum'},
          ],
    }

  filterMarkers() {
    let activefilters = this.state.filters.map((item) => item.selected && item.filter);
    let markers = this.state.allMarkers;

    let filteredmarkers = markers.map((item) => activefilters
    .some(r => item.filter.includes(r)) && item)
    .filter((item) => item)
    this.setState({...this.state, filteredMarkers: filteredmarkers})
  }

  selectedFilter(id) {
    let selectedfilters = this.state.filters
    selectedfilters.map((filter) => filter.id == id ? filter.selected = !filter.selected : null)
    this.setState({...this.state, filters: selectedfilters})
    this.filterMarkers();
  }

  render() {
      return(
        <View>
        <MapView >        
          {this.state.filteredMarkers.map((marker, idx) => (
            <Marker
              key={idx}
              identifier={marker.id}
              coordinate={marker.latlng}
            />
          ))}
        </MapView>
            <FlatList 
            data={this.state.filters}
            renderItem={({item, idx}) => 
            <TouchableOpacity onPress={() => this.selectedFilter(item.id)}>
            <View >
                <Image source={item.img} idx={idx}/>
            </View>
            </TouchableOpacity>          
            }
            />
        </View>

      ) 
  }
}

1 个答案:

答案 0 :(得分:1)

每当您尝试进行任何类型的优化时,通常都会在速度和内存之间进行权衡。但是首先,让我们分析一下您当前的方法:

// don't need to worry here as your filter set is small
let activefilters = this.state.filters.map((item) => item.selected && item.filter)

let markers = this.state.allMarkers
let filteredmarkers = markers
  // will run totalMarkers * activeFilters * filtersPerMarker
  .map((item) => 
    activefilters.some(r => item.filter.includes(r)) && item
  )
  // will run totalMarkers
  .filter((item) => item)

因此,由于您只有几个过滤器,因此,如果要增加更多的标记,则性能应该或多或少地线性增加,这很好。这意味着做口罩之类的事情只会使您获得很小的性能提升。

如果您真的想优化它,那么您将以O(1)为目标,可以通过缓存来实现。为此,您基本上以一种可以执行即时查找的方式来重组数据。如果您的标记是静态的,那很好,但是如果您经常添加和删除标记(或更改其各自的过滤器),则必须制定一种策略来重新缓存数据。您可以执行以下操作:

// run this once, and update when markers are added/removed or marker filters change
const cache = {}
state.allMarkers.forEach(marker => {
  const id = marker.filter.join('-')
  if(!cache[id]){ cache[id] = [] }
  cache[id].push(marker)
})

现在要获取过滤结果,您只需查找具有修改后ID的缓存即可。

const filterId = this.state.filters
  .filter(item => item.selected)
  .map(item => item.filter)
  .join('-')

const filteredMarkers = cache[filterId] || []

可能有更好的方法来处理id,但希望您能理解。


这里的要点在于,它取决于用户与数据的交互方式以及您拥有的数据量。再说一遍,1000足够小,不会引起您算法选择上的任何差异,除了做一个简单的过滤器(如您正在使用的过滤器)以外,要做的任何事情都会不必要地使事情复杂化。任何性能问题也更有可能来自渲染大型集合,而不是组织大型集合。

因此,换句话说,编写最简单,最易读的代码,并且只有在确实有充分理由的情况下才进行优化(即,即使有一个基准,也已经确定并确定了实际瓶颈)。花更多的时间使您的应用程序拥有美好的体验!