使用新数据以恒定时间更新现有列表?

时间:2018-06-16 19:18:31

标签: arrays performance typescript

所以问题是O(1)或Constant Time,我需要比较一个T类数组,它将在以后用其他一些数据集进行更新。这个例子中的项目长度很小,但想象一个更大的数据集,例如2000,你就会遇到问题。使用Typescript如何以最有效的方式使用新列表更新现有列表???



let movies: Array<Movie> = getMovies();
let updatedMovies: Array<Movie> = getUpdatedMovies();

// Delete ones that no longer exist within the new data set
let remainingMovies: Array<Movie> = movies.filter((value) => {
    return updatedMovies.some((value2) => {return value2.identifier == value.identifier});
});

// Update existing items or push a new one (ES6 Only)
updatedMovies.forEach(updatedMovie => {
    let item = remainingMovies.find(value => { return value.identifier == updatedMovie.identifier});
    if (item) {
        item = updatedMovie;
    }
    else {
        remainingMovies.push(updatedMovie);
    }
});
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

如果只是用新数组替换旧数组,那么你只会得到O(1)时间。

let easiestRemainingMovies: Array<Movie> = updatedMovies; // replace, O(1)

如果您需要为数组中的每个元素执行某些操作,则不能比O(n)做得更好。您的现有代码看起来像O(n 2 ),因为它执行嵌套迭代。如果从数组转换为由唯一标识符键入的哈希映射(例如,普通JS对象或Map),则可以获得O(n)或接近它。例如:

// put movies into hash, O(n)
const moviesHash: { [k: string]: Movie | undefined } = {};
movies.forEach(movie => moviesHash[movie.identifier] = movie) 

// process updatedMovies using map, O(n)
let betterRemainingMovies: Movie[] = updatedMovies.map(updatedMovie => {
  let item = moviesHash[updatedMovie.identifier]; // O(1) lookup
  if (item) {
    // update existing item somehow here
    return item;
  } else {
    return updatedMovie;
  }
});

警告&#34;最有效的方式&#34;实现甚至衡量是一个艰难的目标。不同的JavaScript引擎以不同的方式运行。只使用像map()filter()forEach()这样的数组方法,可能比普通的旧for循环慢......或者如果你的JS引擎可以优化,可能不会远离回调函数。通常真正的问题不是最有效的方式&#34;但是,对于我所需要的环境中的真实场景,效率足够高,并且#34;。

希望有所帮助。祝你好运。

答案 1 :(得分:0)

更新n项的时间复杂度至少 O(n)。在你的实现中它大约是O(n * m + k * m),其中字母是3个电影数组的长度。要将其减少到更接近O(n),可以为近常量查找创建查找对象。例如(未测试):

&#13;
&#13;
let movies: Array<Movie> = getMovies(), updatedMovies: Array<Movie> = getUpdatedMovies();

let updatedMoviesLookup = updatedMovies.reduce((obj, val) => (obj[val.identifier] = val, obj), {});

let remainingMovies: Array<Movie> = movies.filter(val => val.identifier in updatedMoviesLookup);
&#13;
&#13;
&#13;