javascript 比较两个数组中的对象以向另一个对象添加或减去

rkttyhzu  于 2023-04-19  发布在  Java
关注(0)|答案(5)|浏览(138)

嘿,
我一直在绞尽脑汁做一个JS算法练习,其中我有两个数组:一个有性别,一个有数字决定他们的年龄。我需要比较两者,并确定有多少是一个性别超过一定的年龄,有多少是相反的性别在一定的年龄。什么是最好的方式来实现它?数组总是有相同的长度。
示例数组为:

gender = ["man","woman","man","man","woman"]
age = [30,20,13,63,9]

我使用了各种for循环来确定有多少是男性和女性,以及18岁以上和18岁以下。
for循环是这样的:

for(let i = 0; i < age.length; i++) {
  if(age[i] >= 18) {
    adults ++
  } else {
    minors ++
  }
}

其中adultsminors的初始值为0
我正在考虑是否应该将它们转换为数组,并在稍后返回数组的长度,因为我必须返回一个数量而不是一个列表。

uyhoqukh

uyhoqukh1#

你可以用Array.reduce实现一种数组压缩,以获得更方便的结构,然后根据需要过滤对象并获得结果的长度:

const genders = ["man", "woman", "man", "man", "woman"]
const ages = [30, 20, 13, 63, 9]
let i = -1;
const persons = genders.reduce((res, cur) => {
  return [
    ...res,
    {
      gender: cur,
      age: ages[++i]
    }
  ]
}, []);

console.log("men above 18", persons.filter(p => p.gender === "man" && p.age >= 18).length);
console.log("women below 18", persons.filter(p => p.gender === "woman" && p.age < 18).length);
console.log("men below 18", persons.filter(p => p.gender === "man" && p.age < 18).length);
console.log("women above 18", persons.filter(p => p.gender === "woman" && p.age >= 18).length);
ryoqjall

ryoqjall2#

仅仅计算adultsminors是不够的。你可能需要adultMenadultWomenminorMenminorWomen。你需要比较年龄和性别。

let gender = ["man","woman","man","man","woman"]
    let age = [30,20,13,63,9]
    let adultMen = 0, adultWomen = 0, minorMen = 0, minorWomen = 0;
    for (let i = 0; i < age.length; i++) {
      if (gender[i] == "man"){
        if (age[i] < 18) minorMen++;
        else adultMen++;
      } else {
        if (age[i] < 18) minorWomen++;
        else adultWomen++;
      }
    }
    console.log(adultMen, adultWomen, minorMen, minorWomen);
omqzjyyz

omqzjyyz3#

这是一个O(n)的解决方案,使用对象作为数据结构:

function countByAge(genders, ages, pivot) {
  // Initialize a data object
  const data = {};

  for (let i = 0, l = genders.length; i < l; i++) {
    const gender = genders[i];
    const age = ages[i];
    
    // If we encounter a man, create a man object
    // that holds counters iff it hasn't been created already.
    // Same thing for a woman.
    if (!(gender in data)) {
      data[gender] = {
        older: 0,
        equal: 0,
        younger: 0
      };
    }

    // Then we simply add one to whichever counter applicable.
    if (age > pivot) {
      data[gender].older++;
    } else if (age === pivot) {
      data[gender].equal++;
    } else {
      data[gender].younger++;
    }
  }
  
  return data;
}

试试看:

/* <ignore> */
console.config({ maximize: true, timeStamps: false, autoScroll: false });
/* </ignore> */

const genders = ['man', 'woman', 'man', 'woman', 'man', 'woman', 'man'];
const ages = [30, 20, 13, 18, 63, 9, 18];
const pivot = 18;

console.log(countByAge(genders, ages, pivot));

function countByAge(genders, ages, pivot) {
  const data = {};

  for (let i = 0, l = genders.length; i < l; i++) {
    const gender = genders[i];
    const age = ages[i];

    if (!(gender in data)) {
      data[gender] = {
        older: 0,
        equal: 0,
        younger: 0
      };
    }

    if (age > pivot) {
      data[gender].older++;
    } else if (age === pivot) {
      data[gender].equal++;
    } else {
      data[gender].younger++;
    }
  }
  
  return data;
}
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

更简洁的版本(0用于年轻人,1用于同等人,2用于老年人):

/* <ignore> */
console.config({ maximize: true, timeStamps: false, autoScroll: false });
/* </ignore> */

const genders = ['man', 'woman', 'man', 'woman', 'man', 'woman', 'man'];
const ages = [30, 20, 13, 18, 63, 9, 18];
const pivot = 18;

console.log(countByAge(genders, ages, pivot));

function countByAge(genders, ages, pivot) {
  const data = {};

  for (let i = 0, l = genders.length; i < l; i++) {
    const gender = genders[i];
    const age = ages[i];
    
    (data[gender] ??= [0, 0, 0])[Math.sign(age - pivot) + 1]++;
  }
  
  return data;
}
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

...或者,如果您喜欢-1/0/1

/* <ignore> */
console.config({ maximize: true, timeStamps: false, autoScroll: false });
/* </ignore> */

const genders = ['man', 'woman', 'man', 'woman', 'man', 'woman', 'man'];
const ages = [30, 20, 13, 18, 63, 9, 18];
const pivot = 18;

console.log(countByAge(genders, ages, pivot));

function countByAge(genders, ages, pivot) {
  const data = {};

  for (let i = 0, l = genders.length; i < l; i++) {
    const gender = genders[i];
    const age = ages[i];
    
    (data[gender] ??= { '-1': 0, 0: 0, 1: 0 })[Math.sign(age - pivot)]++;
  }
  
  return data;
}
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>
h6my8fg2

h6my8fg24#

gender = ["man","woman","man","man","woman"];
age = [30,20,13,63,9];
var adultmen = age.filter(function(obj,i){
                       return obj >=18 && gender[i]=="man";
                   }).length;
var minormen = age.filter(function(obj,i){
                       return obj <18 && gender[i]=="man";
                   }).length;;
var adultwomen = age.filter(function(obj,i){
                       return obj >=18 && gender[i]=="woman";
                   }).length;
var minorwomen = age.filter(function(obj,i){
                       return obj <18 && gender[i]=="woman";
                   }).length;;
nnsrf1az

nnsrf1az5#

我认为我们可以通过抽象一点来使它更强大,更有用。我们有一些与属性名称(“gender”,“age”)相关联的值列表。这些列表具有相同的长度。我们希望查询这些列表的 * 组合 *。
因此,我们可以编写一个泛型combine,它接受像{gender: ['man', 'woman', 'man', 'man', 'woman'], age: [30, 20, 13, 63, 9]}这样的输入,并返回一个函数集合,这里只有querycount,但我们可以想象其他函数。
然后,我们向其中任何一个传递一个 predicate 函数,并获得匹配结果或其计数。

const db = combine({gender: ['man', 'woman', 'man', 'man', 'woman'], age: [30, 20, 13, 63, 9]})

const numberOfAdults = db .count (p => p .age >= 18) 
  //=> 3
const girls = db .query (p => p .gender == 'woman' && p .age < 13) 
  //=> [{gender: "woman", age: 9}]

这是这个想法的一个实现:

// depends on input object where the properties are equal-length arrays 
const combine = (o) => {
  const es = Object .entries (o)
  const data = es [0] [1] .map ((_, i) => Object .fromEntries (es .map (([k, v]) => [k, v [i]])))
  return {
    query: (fn) => data .filter (fn),
    count: (fn) => data .filter (fn) .length
  }
}

const db = combine ({
  gender: ['man', 'woman', 'man', 'man', 'woman'], 
  age: [30, 20, 13, 63, 9]
})

console .log ('You can count those matching a predicate, using `count`')
console .log ('# Adults: ',   db .count (p => p .age >= 18))
console .log ('# Boys: ',     db .count (p => p .gender == 'man' && p .age < 18))
console .log ('# Children: ', db .count (p => p .age < 18))
console .log ('# Females: ',  db .count (p => p .gender == 'woman'))
console .log ('# Girls: ',    db .count (p => p .gender == 'woman' && p .age < 18))
console .log ('# Males: ',    db .count (p => p .gender == 'man'))
console .log ('# Men: ',      db .count (p => p .gender == 'man' && p .age >= 18))
console .log ('# Women: ',    db .count (p => p .gender == 'woman' && p .age >= 18))
console .log ('')
console .log ('Or you can fetch them, using `query`')
console .log ('Drinking age', db.query (p => p .age >= 21))
console .log ('Children: ',   db .query (p => p .age < 18))
.as-console-wrapper {max-height: 100% !important; top: 0}

这并不局限于两个属性,如果我们将eyes: ['blue', 'brown', 'brown', 'hazel', 'blue']添加到输入中,那么我们正在研究的对象也将具有eyes属性。
有一个重要的警告:提供的属性数组必须具有相同的长度。2当然,这是问题陈述中固有的,但它真正的意思是这种技术相当有限。

相关问题