我的作业需要帮助,我遇到了这个问题,但不知道如何找到答案:
考虑一组退休人员,其中任何人在第 X 年开始工作并在第 Y 年退休。创建一个函数,该函数接收遵循以下结构的数组:[[x1,y1],[x2,y2],...[xn,yn]]
并计算哪一年( s) 大多数人都在工作。
考虑:
(x>0, x<y)
;(y>0)
;示例:Input [[1960,2005],[1945,2008],[1938,1999],...]
我试图将最低和最高年份进行比较,并逐年计算有多少人在工作,但没有成功。
编辑:我设法将数组转换为一个数组并对所有工作年份进行排序。现在我需要管理如何找到每年工作的人。我开发的代码如下:
var variety = [[2000,2008],[2003,2009],[2001,2012],[2004,2020],[2003,2021],[1998,2015]], year = [], anos2 = 0, k=0, minYear=0, maxYear=0
function getyear(people){
for(var lin = 0; lin < people.length; lin++){ //Esse for é para transformar a matriz em um único vetor dinamicamente
for(var col = 0; col < people.length-(people.length-2); col++){
year[k] = people[lin][col]
k++
}
}
year.sort(compareNumbers) //Ordena o vetor dos anos trabalhados
console.log(year)
console.log(people)
}
function compareNumbers(a,b){
return a -b
}
getyear(variety)
答案 0 :(得分:2)
从您的问题来看,您似乎很难解决如何解决问题,而不是如何编写代码。希望以下见解对您有所帮助。
如何创建一个初始值为 0 的从 minYear 到 maxYear 的整数数组。 每当您有一个用户在 X 年开始工作并在 Y 年退休时,您只需将数组中每一年的数字递增。
因此,从 1960 年到 2015 年工作的人将在数组中为 1960 年到 2015 年的值提供值 1。对每个用户重复。
之后,您可以循环数组以查找数组中的最大值和最小值。这也简化了逻辑,因为可能有多个最大峰值和多个最小峰值。
还有一种替代方法,即不创建任何数组并从 minYear 到 maxYear 每年循环一次,从而不分配尽可能多的内存。对于那些年中的每一年,您都需要为所有员工循环以计算该年有多少人在工作。将第一年保存为最小值和最大值,每隔一年,如果该值高于最高值或低于最低值,只需更新它并将其用作新的峰值。这使用最少的内存,但会使用更多的 CPU。
总有一些替代方法可以实现更好的 CPU 和内存效率。但是对于初学者来说,这两种方法都是可以接受的。
答案 1 :(得分:1)
功能:
const getCounts = (arr = []) =>
{
const years = {};
let x, y, year;
arr.forEach( item => {
x = item[0];
y = item[1];
for ( year = x ; year <= y ; ++year )
{
if(years[year] === undefined)
{
years[year] = 0;
}
years[year]++;
}
});
return years;
}
排序:
const output = getCounts([[1960,2005],[1945,2008],[1938,1999]]);
console.log( Object.entries(output).sort( (a,b) => b[1] - a[1] ) );
答案 2 :(得分:1)
以下方法利用了 this article 中描述的算法。与之前的答案不同,这不会将 all 范围不必要地分解为年份,也不会在每个范围内迭代每年。相反,它返回同时工作的最大人数,以及雇用该人数的一系列范围。如果需要,可以将范围数组转换为年份数组。
const f = input=>Object.entries(
// sum up entries/exits by year
input.reduce(
(a,[s,e])=>(
a[s] = (a[s]||0)+1,
a[e] = (a[e]||0)-1,
a
),{}
))
// convert years back to numbers
.map(([s,e])=>[1*s,e])
// sort ascending by year
.sort(([r],[l])=>r-l)
.reduce((a,[y,c])=>{
a.count += c;
switch (Math
.sign(a.count - a.r.max)) {
case 1: // count > max
// set max; clear ranges
a.r = {max:a.count,ranges:[]};
// fall through
case 0: // count === 0
// open new range
a.r.ranges.push([y]);
break;
case -1: // count < max
// close range, if open
a.r.ranges.push([
...a.r.ranges.pop(), y
].slice(0,2));
break;
}
return a;
},{ // initial values
count:0,
r:{max:0,ranges:[]}
})
// return results object
.r;
例如:
const input = [
[1960,2005],
[1945,2008],
[1938,1999]
];
console.log(f(input1));
这将导致:
{ max: 3, ranges: [ [ 1960, 1999 ] ] }
表示同时雇用的最大工人数为 3,并且在 1960 年至 1999 年(含)期间同时雇用了 3 名工人。
在下面一个更复杂的例子中,为简洁起见,我多年来一直使用小整数:
const input = [
[1,9],
[1,2],
[8,9],
[2,3],
[5,7],
[7,9],
[5,6],
[8,9],
[5,9],
[4,8],
[1,3]
];
console.log(f(input));
结果是:
{ max: 5, ranges: [ [ 5, 6 ], [ 8, 9 ] ] }
表示同时最大工人数为 5,并且在两个不重叠的时间间隔内同时雇用 5 名工人:第 5 年到第 6 年和第 8 年到第 9 年。
如果需要,以下函数可用于将范围数组分解为年份的平面数组:
const explode = ranges=>
[].concat(
...ranges.map(([s,e])=>Array.from(
{length:e-s+1},(_,i)=>i+s
))
);
例如:
const input = [
[1,5],
[6,7],
[9,9]
];
console.log(explode(input));
将导致以下结果:
[ 1, 2, 3, 4, 5, 6, 7, 9 ]
答案 3 :(得分:0)
也许你可以这样做;
var years = [[2000,2008],[2003,2009],[2001,2012],[2004,2020],[2003,2021],[1998,2015]];
result = years.map(ys => Array.from({length:ys[1]-ys[0]+1}, (_,i) => ys[0]+i))
.reduce((p,c) => p.filter(e => c.includes(e)));
console.log(result);
years.map(ys => Array.from({length:ys[1]-ys[0]+1}, (_,i) => ys[0]+i))
part 将您的 [[2000,2008],[2003,2009],[2001,2012],[2004,2020],[2003,2021],[1998,2015]]
数组变成
[[2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008]
,[2003, 2004, 2005, 2006, 2007, 2008, 2009]
,[2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012]
,[2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020]
,[2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021]
,[1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015]
]
而 .reduce((p,c) => p.filter(e => c.includes(e)))
部分只是 reduces by intersecting。
这只是一种幼稚但直观的方式。从这个想法发展而来,您应该能够通过一个 .reduce()
阶段来做到这一点。所以它仍然是一个家庭作业。
所以上面的解决方案对于给定的数据集是可以的,但是有一个正确的评论。所以我在这里切换到一个高效的代码。它返回一个对象,其中属性是受制于人们工作的年数,值是每年的人数。
var years = [[2000,2008],[2003,2009],[2001,2012],[2004,2020],[2003,2021],[1998,2015]];
result = years.reduce(function(r,ys) {
for (var y = ys[0]; y <= ys[1]; y++){
r[y] = r[y] ? r[y]+1 : 1
}
return r;
},{});
console.log(result);
.as-console-wrapper {
max-height: 100% !important
}