Как получить из массива объектов все уникальные значения свойства, являющегося самим массивом - PullRequest
0 голосов
/ 26 июня 2018

Этот ответ уже близок , и есть несколько ответов, как получить уникальные значения в массиве (удалить дубликаты), хотя я не могу заставить его работать для случая, когда речь идет о массиве объектов, и свойство, которое должно быть отфильтровано, является массивом. Извините, я новичок в JS. Спасибо за помощь.

У меня есть массив таких объектов

const posts = [
  post1: {
    id: 1,
    title: 'One',
    tags: ['tagA', 'tagB']
    },
  post2: {
    id: 2,
    title: 'Two',
    tags: ['tagB', 'tagC']    
    },
  post3: {
    id: 3,
    title: 'Three',
    tags: ['tagB', tagC, tagD]    
    ]

Мне понадобится массив всех уникальных тегов ... в приведенном выше случае с ожидаемым выводом, подобным этому:

// [tagA, tagB, tagC, tagD] 

РЕДАКТИРОВАТЬ / ОБНОВИТЬ

Ключ в массиве объектов используется для управления состоянием реагирующего компонента ... например,

constructor(props) {
super(props);

this.state = {
  posts: []
};
}

...

updatePost = (key, updatedPost) => {
//1. Take copy of the current this.state.
const posts = {...this.state.texts};
//2. Update that state
posts[key] = updatedPost;
//3. Set that to state
const options = { encrypt: false }
putFile(postsFileName, JSON.stringify(posts), options)
  .then(() => {
    this.setState({
      posts: posts
    })
  })
  };

Ответы [ 5 ]

0 голосов
/ 26 июня 2018

Если вы хотите использовать функциональную библиотеку, такую ​​как Ramda.js , вы можете сделать это:

const posts = [
	{
		id: 1,
		title: 'One',
		tags: ['tagA', 'tagB'],
	},
	{
		id: 2,
		title: 'Two',
		tags: ['tagB', 'tagC'],
	},
	{
		id: 3,
		title: 'Three',
		tags: ['tagB', 'tagC', 'tagD'],
	},
];

var unique = R.uniq(R.flatten(R.map(R.prop('tags'), posts)))
console.log(unique)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.25.0/ramda.min.js"></script>
0 голосов
/ 26 июня 2018

с помощью jquery вы можете сделать что-то похожее на это (не проверено):

var results = [];
$.each(myObject, function(key,valueObj){
    var check.isArray(obj);
    if(check){
        alert(key + "/" + valueObj );
        /*replace repeat*/
        var sorted_check = check.slice().sort(); // You can define the comparing function here. 
                                     // JS by default uses a crappy string compare.
                                     // (we use slice to clone the array so the
                                     // original array won't be modified)

        for (var i = 0; i < sorted_check.length - 1; i++) {
            if (sorted_check[i + 1] == sorted_check[i]) {
                results.push(sorted_check[i]);
            }
        }
    }
});

и хороший способ с indexof:

Array.prototype.unique = function() {
    var a = [];
    for ( i = 0; i < this.length; i++ ) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }

    this.length = 0;
    for ( i = 0; i < a.length; i++ ) {
        this.push( a[i] );
    }

    return this;
}

Array.prototype.unique = function() {
    var a = [];
    for ( i = 0; i < this.length; i++ ) {
        var current = this[i];
        if (a.indexOf(current) < 0) a.push(current);
    }
    return a;
}

и следуй UP:

Array.prototype.unique = function(mutate) {
    var unique = this.reduce(function(accum, current) {
        if (accum.indexOf(current) < 0) {
            accum.push(current);
        }
        return accum;
    }, []);
    if (mutate) {
        this.length = 0;
        for (let i = 0; i < unique.length; ++i) {
            this.push(unique[i]);
        }
        return this;
    }
    return unique;
}
0 голосов
/ 26 июня 2018

Вы можете reduce свои посты и итерировать по тегам и выдвигать их к результату, с которым вы еще не сталкивались:

const posts = [
  {
    id: 1,
    title: "One",
    tags: ["tagA", "tagB"]
  },
  {
    id: 2,
    title: "Two",
    tags: ["tagB", "tagC"]
  },
  {
    id: 3,
    title: "Three",
    tags: ["tagB", "tagC", "tagD"]
  }
];

const uniqueTags = posts.reduce((result, post) => {
  post.tags.forEach(tag => {
    if (!result.includes(tag)) {
      result.push(tag);
    }
  });

  return result;
}, []);

console.log(uniqueTags);
0 голосов
/ 26 июня 2018

Предполагается, что вы знаете, что ключ массива всегда 'теги'.

let filter = {};
let result = [];

posts.forEach(post => {
  const tags = post['tags'];
  tags.forEach(tag => {
    if (!filter.hasOwnProperty(tag)) {
      result.push(tag);
      filter[tag] = true; 
    }
  });
});
0 голосов
/ 26 июня 2018

Предполагается, что вход имеет формат [ {} , {} ]:

Вы можете использовать concat и map для выравнивания массива. Используйте new Set, чтобы получить уникальные значения.

const posts = [{"id":1,"title":"One","tags":["tagA","tagB"]},{"id":2,"title":"Two","tags":["tagB","tagC"]},{"id":3,"title":"Three","tags":["tagB","tagC","tagD"]}];

var result = [...new Set([].concat(...posts.map(o => o.tags)))];

console.log(result);

Если переменная является объектом ({a:{} , b:{} }), вы можете использовать Object.values для преобразования объекта в массив.

const posts = {"post1":{"id":1,"title":"One","tags":["tagA","tagB"]},"post2":{"id":2,"title":"Two","tags":["tagB","tagC"]},"post3":{"id":3,"title":"Three","tags":["tagB","tagC","tagD"]}}

var result = [...new Set([].concat(...Object.values(posts).map(o => o.tags)))];

console.log(result);
...