我创建了一个像这样的对象数组:
var places = [];
var a = {};
a.lat = 12.123;
a.lng = 13.213;
a.city = "New York";
places.push(a);
var b = {};
b.lat = 3.123;
b.lng = 2.213;
b.city = "New York";
places.push(b);
...
我正在尝试创建一个新的数组,过滤场所只包含不具有相同城市属性的对象(lat / lng重复项是可以的)。是否有内置的JS或Jquery函数来实现这一目标?
答案 0 :(得分:44)
我可能会在过滤过程中使用flags对象,如下所示:
var flags = {};
var newPlaces = places.filter(function(entry) {
if (flags[entry.city]) {
return false;
}
flags[entry.city] = true;
return true;
});
使用来自ECMAScript5(ES5)的Array#filter
,这是可以填充的ES5添加之一(为几个选项搜索“es5 shim”)。
你可以在没有filter
的情况下做到这一点,当然,它只是更冗长:
var flags = {};
var newPlaces = [];
var index;
for (index = 0; index < places.length; ++index) {
if (!flags[entry.city]) {
flags[entry.city] = true;
newPlaces.push(entry);
}
});
以上两种情况都假定应该保留具有给定城市的第一个对象,并且丢弃所有其他对象。
注意:正如user2736012指出的那样,对于名称与if (flags[entry.city])
上存在的属性(例如Object.prototype
)相同的城市,我的测试toString
将成立。在这种情况下非常不可能,但有四种方法可以避免这种可能性:
(我通常喜欢的解决方案)创建没有原型的对象:var flags = Object.create(null);
。这是ES5的一个功能。请注意,对于像IE8这样的过时浏览器,这不能被填充(Object.create
的单参数版本可以是,除非,当该参数的值为null
时)。
使用hasOwnProperty
进行测试,例如if (flags.hasOwnProperty(entry.city))
为您知道任何Object.prototype
属性不存在的内容添加前缀,例如xx
:
var key = "xx" + entry.city;
if (flags[key]) {
// ...
}
flags[key] = true;
从ES2015开始,您可以改为使用Set
:
const flags = new Set();
const newPlaces = places.filter(entry => {
if (flags.has(entry.city)) {
return false;
}
flags.add(entry.city);
return true;
});
答案 1 :(得分:19)
最短的,但不是最佳性能(请参阅下面的更新)解决方案:
if ( user == null)
答案 2 :(得分:4)
我的建议:
Array.prototype.uniqueCity = function() {
var processed = [];
for (var i=this.length-1; i>=0; i--){
if (processed.indexOf(this[i].city)<0) {
processed.push(this[i].city);
} else {
this.splice(i, 1);
}
}
}
正在使用中:
places.uniqueCity();
或
Array.prototype.uniqueObjectArray = function(field) {
var processed = [];
for (var i=this.length-1; i>=0; i--) {
if (this[i].hasOwnProperty(field)) {
if (processed.indexOf(this[i][field])<0) {
processed.push(this[i][field]);
} else {
this.splice(i, 1);
}
}
}
}
places.uniqueObjectArray('city');
通过上述内容,您可以按对象中的任何字段对数组进行排序,即使某些对象不存在。
或
function uniqueCity(array) {
var processed = [];
for (var i=array.length-1; i>=0; i--){
if (processed.indexOf(array[i].city)<0) {
processed.push(array[i].city);
} else {
array.splice(i, 1);
}
}
return array;
}
places = uniqueCity(places);
答案 3 :(得分:3)
https://lodash.com/docs#uniqBy
https://github.com/lodash/lodash/blob/4.13.1/lodash.js#L7711
/**
* This method is like `_.uniq` except that it accepts `iteratee` which is
* invoked for each element in `array` to generate the criterion by which
* uniqueness is computed. The iteratee is invoked with one argument: (value).
*
* @static
* @memberOf _
* @since 4.0.0
* @category Array
* @param {Array} array The array to inspect.
* @param {Array|Function|Object|string} [iteratee=_.identity]
* The iteratee invoked per element.
* @returns {Array} Returns the new duplicate free array.
* @example
*
* _.uniqBy([2.1, 1.2, 2.3], Math.floor);
* // => [2.1, 1.2]
*
* // The `_.property` iteratee shorthand.
* _.uniqBy([{ 'x': 1 }, { 'x': 2 }, { 'x': 1 }], 'x');
* // => [{ 'x': 1 }, { 'x': 2 }]
*/
答案 4 :(得分:3)
我在@IgorL解决方案上进行了一些扩展,但扩展了原型并为其提供了一个选择器函数而不是属性,使其更灵活:
Array.prototype.unique = function(selector) {
return this.filter((e, i) => this.findIndex((a) => {
if (selector) {
return selector(a) === selector(e);
}
return a === e;
}) === i);
};
<强>用法:强>
// with no param it uses strict equals (===) against the object
let primArr = ['one','one','two','three','one']
primArr.unique() // ['one','two','three']
let a = {foo:123}
let b = {foo:123}
let fooArr = [a,a,b]
fooArr.unique() //[a,b]
// alternatively, you can pass a selector function
fooArr.unique(item=>item.foo) //[{foo:123}] (first "unique" item returned)
绝对不是最高效的方法,但只要选择器很简单并且数组不是很大,它应该可以正常工作。
Array.prototype.unique = function<T>(this: T[], selector?: (item: T) => object): T[] {
return this.filter((e, i) => this.findIndex((a) => {
if (selector) {
return selector(a) === selector(e);
}
return a === e;
}) === i);
};
答案 5 :(得分:1)
正如评论中所指出的,你可以使用一个对象作为一个地图,它可以避免重复,然后你可以枚举对象的属性。
工作小提琴:http://jsfiddle.net/gPRPQ/1/
var places = [];
var a = {};
a.lat = 12.123;
a.lng = 13.213;
a.city = "New York";
places.push(a);
var b = {};
b.lat = 3.123;
b.lng = 2.213;
b.city = "New York";
places.push(b);
var unique = {}
for (var i = 0; i < places.length; i++) {
var place = places[i];
unique[place.city] = place;
}
for (var name in unique) {
var place = unique[name];
console.log(place);
}
答案 6 :(得分:1)
var places = [];
var a = {};
a.lat = 12.123;
a.lng = 13.213;
a.city = "New York";
places.push(a);
var b = {};
b.lat = 3.123;
b.lng = 2.213;
b.city = "New York";
places.push(b);
getUniqAR(places,'city'); //Return Uniq Array by property
function getUniqAR(Data,filter){
var uniar =[];
Data.forEach(function(item,ind,arr){
var dupi=false;
if(!uniar.length) uniar.push(item) //push first obj into uniq array
uniar.forEach(function(item2, ind2,arr){
if(item2[filter] == item[filter]){ //check each obj prop of uniq array
dupi=true; //if values are same put duplicate is true
}
})
if(!dupi){ uniar.push(item)} //if no duplicate insert to uniq
})
console.log(uniar)
return uniar;
}
答案 7 :(得分:1)
另一个选择:
const s = '2018-11-29T09:54:46.863207Z';
let [y, m, d, hh, mm, ss, ms] = s.match(/\d+/g);
let date = new Date(Date.UTC(y, m - 1, d, hh, mm, ss, ms));
let formatted = date.toLocaleString();
console.log(formatted);
您可以将其粘贴到控制台上以查看其工作情况。 它应该适用于所介绍的场景和其他一些场景。
答案 8 :(得分:0)
您可以使用地图,因此具有相同键属性的条目(在您的情况下&#39;城市&#39;)仅出现一次
module.exports = (array, prop) => {
const keyValueArray = array.map(entry => [entry[prop], entry]);
const map = new Map(keyValueArray);
return Array.from(map.values());
};
有关地图和数组对象here
的详细信息答案 9 :(得分:0)
用简单的Javascript
代码从places
数组列表中删除重复的城市是
var places = [{ 'lat': 12.123, 'lng': 13.213, 'city': "New York"},
{ 'lat': 3.123, 'lng': 2.213, 'city': "New York"},
{ 'lat': 43.123, 'lng': 12.213, 'city': "London"}];
var unique = [];
var tempArr = [];
places.forEach((value, index) => {
if (unique.indexOf(value.city) === -1) {
unique.push(value.city);
} else {
tempArr.push(index);
}
});
tempArr.reverse();
tempArr.forEach(ele => {
places.splice(ele, 1);
});
console.log(places);
答案 10 :(得分:0)
基于上述https://stackoverflow.com/a/18773857/49564的通用打字稿答案:
export function isDistinct<T>(mapper: (value: T) => string): (value: T) => boolean {
const keys: { [index: string]: boolean } = {};
return (entry: T) => {
const key = mapper(entry);
if (keys[key] !== undefined) {
return false;
}
return keys[key] = true;
};
}
// Usage example:
const items = [ { id: 1 }, { id: 2 }, { id: 3 }, { id: 1 } ];
const unique = items.filter(isDistinct(i => i.id));
答案 11 :(得分:0)
我想你想要这个
注意: 不需要库。
let array = [{ id: 1}, {id: 2}, {id: 3}];
function addUniqeObj(data) {
let index = -1;
for(let i = 0, i < array.length; i++) {
if(array[i].id === data.id) {
index = i;
}
}
if(index > -1) {
array[index] = data;
} else {
array.push(data)
}
}
答案 12 :(得分:0)
我们可以使用JavaScript Map通过任何属性来创建唯一对象列表。
例如:
var places = [{ 'lat': 12.123, 'lng': 13.213, 'city': "New York"},
{ 'lat': 3.123, 'lng': 2.213, 'city': "New York"},
{ 'lat': 43.123, 'lng': 12.213, 'city': "London"}];
var cityMap = new Map();
places.forEach(p=> cityMap.set(p.city, p));
console.log([...cityMap.values()]);
执行代码段以查看结果。
答案 13 :(得分:0)
rafaelbiten方法的另一种形式:
const dedupExample = [
{id: 1, c: 'whatever'},
{id: 1, c: '1whatever'},
{id: 2, c: '2whatever'},
{id: 2, c: '2whatever'},
{id: 3, c: '2whatever'},
]
const getUniqueBy = (prop, list) => {
const objUniq = list.reduce((res, item) => ({ ...res, [item[prop]]: item }), {})
return Object.keys(objUniq).map(item => objUniq[item])
}
const uniq = getUniqueBy('id', dedupExample)
console.info('info', { uniq })
/* [
{id: 1, c: 'whatever'},
{id: 2, c: '2whatever'},
{id: 3, c: '2whatever'},
] */
答案 14 :(得分:0)
您可以使用filter
Set
,方法是仅包含属性值尚未添加到Set
的元素(之后应将其添加到{{1 }}。可以使用逻辑和运算符(Set
)在一行中完成。
以下是一个通用函数,用于基于特定属性(&&
)获得对象的唯一数组(arr
)。请注意,如果重复,则仅保留具有属性值的第一个对象。
prop
演示:
const getUniqueBy = (arr, prop) => {
const set = new Set;
return arr.filter(o => !set.has(o[prop]) && set.add(o[prop]));
};
答案 15 :(得分:-1)
这个帖子可能很旧,但我认为我应该分享它。它基于Pure JavaScript,并根据指定的属性删除重复对象。
function removeDuplicates(originalArray, properties) {
var newArray = [];
var index = 0;
var lookupObject = {};
var totalProperties = properties.length;
for (var i = 0; i < originalArray.length; i++) {
var exists = false;
for (var a = 0; a < newArray.length; a++) {
var propsFound = 0;
for (var b = 0; b < totalProperties; b++) {
if (originalArray[i][properties[b]] == newArray[a][properties[b]]) {
propsFound++;
}
}
//If there is a match then break the for loop
if (propsFound == totalProperties) {
exists = true;
break;
}
} //End of New Array
if (!exists) {
newArray[index] = originalArray[i];
index++;
}
} //End of originalArray
return newArray;
}
您可以查看小提琴here