2016-04-06 2 views
0

У меня есть массив объектов нить, как этотJavascript найти объект в объект-массив, хотя конкретный объект недвижимости

threadlist:Thread[]= [thread{id:1},thread{id:2},thread{id:3},...] 

У меня также есть массив ThreadRelation внутри объекта пользователя, как показано ниже, чтобы сохранить, если пользователь имеет определенный нить добавлена ​​в закладки или нет. Обратите внимание, что идентификатор в Thread не совпадает с его местом в массиве.

user{ 
    user_id:number,...(some other user typical properties) 
    threadRelations:ThreadRelation[]=[ 
    threadRelation{ 
    id:2,//relates to id property of a Thread object 
    isBookmarked:true 
    }, 
    threadRelation{ 
    id:18, 
    isBookmarked:true 
    },.. 
]} 

Я хочу создать функцию, которая возвращает массив только с закладками нитей пользователя. Я могу достичь этого, используя два for-loops и if-statements, но я не думаю, что он эффективен. Есть ли методы, когда я могу найти этот конкретный объект внутри массива напрямую?

updateBookmarkedList(){ 
     for (var i = 0; i < this.activeUser.threadsRelation.length; i++){ 
     if (this.activeUser.threadsRelation[i].bookmarked == true){ 
      var searchId = this.activeUser.threadsRelation[i].id; 
      for (var j = 0; j < this.threadlist.length; j++){ 
      if (this.threadlist[j].id == searchId){ 
       this.userBookmarkedList.push(this.threadlist[j]) 
      } 
      } 
     } 
     } 
    } 

Спасибо!

+1

Используйте ['Array.prototype.filter'] (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter)! Обратите внимание, что ваш JSON недействителен, если это не псевдокод. В этом случае вы должны предоставить полный пример того, что у вас есть (с достоверными данными). –

+0

@ Mr.Polywhirl Рассмотрите возможность принятия этого ответа. – Alex

ответ

1

If Thread.id - уникальный идентификатор, тогда вы действительно должны использовать Map вместо Array объектов без ключей. Без ключей вам придется перебирать массивы без других вариантов.

При повторении Array попробуйте использовать встроенные методы итерации, такие как forEach. Они более эффективны и выглядят более аккуратно, чем петли.

Чтобы сделать дополнение к @Tamas-Hegedus's answer using ES6 iterator feature, я создал JSFiddle, используя текущую версию JavaScript, чтобы сделать «Array-Map», вы можете заменить его Map если Thread.id не является числовым значением.

См. JSFiddle.

1

С Array.prototype.filter, вы можете сохранить только взаимосвязь с закладками. Из этого отфильтрованного списка вы можете создать список потоков, основанный на критериях id.

var threads = [ 
 
    { id: 1 }, 
 
    { id: 2 }, 
 
    { id: 3 } 
 
]; 
 

 
var users = [{ 
 
    user_id: 1, 
 
    threadRelations: [ 
 
    { id: 2, isBookmarked: true }, 
 
    { id: 18, isBookmarked: true } 
 
    ] 
 
}]; 
 

 
var userBookmarkedList = updateBookmarkedList(users[0], threads); 
 
document.body.innerHTML = '<pre>Threads -> ' + JSON.stringify(userBookmarkedList, null, 2) + '</pre>'; 
 

 
function updateBookmarkedList(user, threads) { 
 
    return user.threadRelations.filter(function(threadRelation) { 
 
    return threadRelation.isBookmarked === true; 
 
    }).reduce(function(list, threadRelation) { 
 
    return list.concat(threads.filter(function(thread) { 
 
     return thread.id === threadRelation.id; 
 
    })); 
 
    }, []); 
 
}

Вы также можете создать карту, чтобы улучшить производительность поиска.

var threads = [ 
 
    { id: 1 }, 
 
    { id: 2 }, 
 
    { id: 3 } 
 
]; 
 

 
var users = [{ 
 
    user_id: 1, 
 
    threadRelations: [ 
 
    { id: 2, isBookmarked: true }, 
 
    { id: 18, isBookmarked: true } 
 
    ] 
 
}]; 
 

 
var threadMap   = mapBy(threads, 'id'); 
 
var userBookmarkedList = retrieveBookmarkedThreads(users[0], threadMap); 
 
document.body.innerHTML = '<pre>Threads -> ' + JSON.stringify(userBookmarkedList, null, 2) + '</pre>'; 
 

 
function mapBy(list, key) { 
 
    return list.reduce(function(map, item) { 
 
    map[item[key]] = item; 
 
    return map; 
 
    }, {}); 
 
} 
 

 
function retrieveBookmarkedThreads(user, threadMap) { 
 
    return user.threadRelations.filter(function(threadRelation) { 
 
    return threadRelation.isBookmarked === true; 
 
    }).reduce(function(list, threadRelation) { 
 
    return (function(thread) { 
 
     return thread != null ? list.concat(thread) : list; 
 
    }(threadMap[threadRelation.id])); 
 
    }, []); 
 
}

1

Почему вы не держите карту в "нити" по их идентификатору?

Чтобы создать карту из массива:

var threadsById = new Map(threads.map(t => [t.id, t])); 

Чтобы получить, если ThreadId присутствует:

if (threadsById.has(threadRelation.id)) { 
    ... 
} 

Чтобы получить нить его ID:

var currentThread = threadsById.get(threadRelation.id);