Jor*_*tad 8 javascript arrays date
我看到这个问题经常被问到常规的javascript数组,但是如果有一个日期数组,那么答案似乎都无法解决.
我可以通过试验错误地解决这个问题,但如果我问的话,我确实看到了其他人的一些好处.
基本上如果你有一个javascript数组的日期可能有重复,需要过滤到一个没有重复的数组,最好的方法是什么?
我尝试过ES6解决方案,Array.from(new Set(arr))但它只返回相同的数组.
我也试过了
Array.prototype.unique = function() {
var a = [];
for (var i=0, l=this.length; i<l; i++)
if (a.indexOf(this[i]) === -1)
a.push(this[i]);
return a;
}
Run Code Online (Sandbox Code Playgroud)
两者都来自数组中的唯一值
但是没有工作,看起来像是indexOf在日期对象上不起作用.
这是我的数组生成atm的方式
//this is an array generated from ajax data,
//its a year over year comparison with a separate year,
//so to create a reliable date objects I force it to use the same year.
data.map(d => {
dp = new Date(Date.parse(d.date + '-' + d.year));
dp.setFullYear(2000);
return dp;
})
Run Code Online (Sandbox Code Playgroud)
它大约有100个左右不同的日子,但它总是以350左右的指数结束.
Ser*_*kiy 11
ES6 道路:
datesArray.filter((date, i, self) =>
self.findIndex(d => d.getTime() === date.getTime()) === i
)
Run Code Online (Sandbox Code Playgroud)
Tim*_*imo 10
如果比较两个日期===,则比较两个日期对象的引用.表示相同日期的两个对象仍然是不同的对象.
相反,比较以下时间戳Date.prototype.getTime():
function isDateInArray(needle, haystack) {
for (var i = 0; i < haystack.length; i++) {
if (needle.getTime() === haystack[i].getTime()) {
return true;
}
}
return false;
}
var dates = [
new Date('October 1, 2016 12:00:00 GMT+0000'),
new Date('October 2, 2016 12:00:00 GMT+0000'),
new Date('October 3, 2016 12:00:00 GMT+0000'),
new Date('October 2, 2016 12:00:00 GMT+0000')
];
var uniqueDates = [];
for (var i = 0; i < dates.length; i++) {
if (!isDateInArray(dates[i], uniqueDates)) {
uniqueDates.push(dates[i]);
}
}
console.log(uniqueDates);Run Code Online (Sandbox Code Playgroud)
优化和错误处理取决于您.
您可以使用查找做一个简单的过滤器,但是您需要将日期转换为可以比较的内容,因为JavaScript中两个对象永远都不相同,除非它是对相同对象的两个引用。
const dates = [
new Date(2016, 09, 30, 10, 35, 40, 0),
new Date(2016, 09, 30, 10, 35, 40, 0), //same
new Date(2016, 09, 30, 10, 35, 40, 0), //same
new Date(1995, 07, 15, 03, 15, 05, 0) //different
];
function filterUniqueDates(data) {
const lookup = new Set();
return data.filter(date => {
const serialised = date.getTime();
if (lookup.has(serialised)) {
return false;
} else {
lookup.add(serialised);
return true;
}
})
}
console.log(filterUniqueDates(dates));Run Code Online (Sandbox Code Playgroud)
如果您只想更改确定唯一性的方式来过滤任何内容,则可以进一步概括
const dates = [
new Date(2016, 09, 30, 10, 35, 40, 0),
new Date(2016, 09, 30, 10, 35, 40, 0), //same
new Date(2016, 09, 30, 10, 35, 40, 0), //same
new Date(1995, 07, 15, 03, 15, 05, 0) //different
];
const dateSerialisation = date => date.getTime(); // this is the previous logic for dates, but extracted
//as primitives, these can be compared for uniqueness without anything extra
const numbers = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4];
const strings = ["a", "b", "b", "c", "c", "c"];
const people = [
{name: "Alice", age: 20},
{name: "Bob", age: 30},
{name: "Bob", age: 40}, //technically the same
{name: "Carol", age: 50},
{name: "Carol", age: 60}, //technically the same
{name: "Carol", age: 70} //technically the same
]
//let's assume that a person with the same name is the same person regardless of anything else
const peopleSerialisation = person => person.name;
/*
* this now accepts a transformation function that will be used
* to find duplicates. The default is an identity function that simply returns the same item.
*/
function filterUnique(data, canonicalize = x => x) {
const lookup = new Set();
return data.filter(item => {
const serialised = canonicalize(item); //use extract the value by which items are considered unique
if (lookup.has(serialised)) {
return false;
} else {
lookup.add(serialised);
return true;
}
})
}
console.log("dates", filterUnique(dates, dateSerialisation));
console.log("numbers", filterUnique(numbers));
console.log("strings", filterUnique(strings));
console.log("people", filterUnique(people, peopleSerialisation));Run Code Online (Sandbox Code Playgroud)
这使用的是ES6,但转换为符合ES5的代码很简单-删除粗箭头功能,默认参数,new Set()这就是您需要的:
function filterUnique(data, canonicalize) {
if (!canonicalize) {
canonicalize = function(x) { return x; }
}
var lookup = {};
return data.filter(function(item) {
var serialised = canonicalize(item);
if (lookup.hasOwnProperty(serialised)) {
return false;
} else {
lookup[serialised] = true;
return true;
}
})
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4492 次 |
| 最近记录: |