在数组中匹配2个元素

问题描述 投票:-2回答:3

假设我有一个人类

class Person {
    constructor(name, sign, likes) {
        this.name = name;
        this.sign = sign;
        this.likes = likes
    }
}

var a = new Person("Jim", "virgo", "piscis");
var b = new Person("Sara", "sagitarus", ["piscis", "sagitarus"]);
var c = new Person("Sam", "aries", "Leo");

这个班级描述了他们的十二生肖,以及他们最喜欢的十二生肖。

然后,我有一群人:

var people = [a, b, c, ....]

我想要实现的是,从数组的开始,根据他们的符号和他们感兴趣的内容找到第一个可能的匹配。

例如:

  • 如果数组中的第一个项目是一个有标志的人,对符号处女座的人感兴趣,请在数组中搜索对白羊座感兴趣的符号处女座的第一个人。
  • 如果数组中的第一个项目是Aries对处女座感兴趣的人,但阵列中没有人是对白羊座感兴趣的处女座,那么继续尝试匹配阵列中的下一个人。
  • 如果数组中的第一个项目是一个有星座的人,那么Aries会对有白羊座的人感兴趣,请在阵列中搜索第一个拥有对白羊座感兴趣的符号处女座的人,但不包括他自己。

我期望得到的是:

  • 两个人匹配
  • 相同的人群,但从列表中删除的那两个人

像这样的东西:

var match = matchPair(my_people_array);
// match is an array of 2 Persons
// match is falsy in case of no matches
// my_people_array is 2 items shorter (or a new array, not necessary to modify the original array)

我昨天试图解决它很长一段时间,但即使接近工作我也无法找到任何解决方案。

我怎么能在JS中实现这个结果?

UPDATE

因为我不想给人的印象是我没有先自己尝试任何东西,所以这是我能想到的最好的,即使我知道它不起作用:

function match(people) {
    for (var i = 0; i < people.length; i++) {
        var person = people[i];
        var match = people.find((candidate)) {
            return candidate !== person && candidate.likes.includes(person.sign) && person.likes.includes(candidate.sign)
        }

        if (!match) return false

        return [person, match]
    }
}

虽然这让我得到了一些比赛,但我也让不止一组的人匹配

更新2:

我将举一些例子来看看是否更清楚地解释了这个想法

// CASE 1

var persons = [
    new Person("Jim", "virgo", ["aries"]),
    new Person("John", "aries", ["virgo"])
    new Person("Justin", "aries", ["piscis"])
];

matchCouple(persons)
// returns an array with Jim and John
// "persons" contains Justin only

// CASE 2

var persons = [
    new Person("Jim", "virgo", ["virgo"]),
    new Person("John", "virgo", ["virgo"])
];

matchCouple(persons)
// returns an array with Jim and John
// Beware not to pair Jim with himself
// "persons" is empty

// CASE 3

var persons = [
    new Person("Jim", "virgo", ["aries"]),
    new Person("John", "piscis", ["virgo"])
];

matchCouple(persons)
// returns falsy value
// persons does not change

// CASE 4

var persons = [
    new Person("Justin", "aries", ["piscis"]),
    new Person("Jim", "virgo", ["aries"]),
    new Person("John", "aries", ["virgo"])
];

matchCouple(persons)
// returns an array with Jim and John, skipping Justin because he had no matches
// "persons" contains Justin only
javascript arrays ecmascript-5
3个回答
1
投票

在这里,我们减少你的数组,并找到一个匹配基于原始阵列的星号(ss)中的第一个人对likes

let people = [
	{ss: 'aries', likes: 'virgo'},
  {ss: 'cancer', likes: 'scorpio'},
  {ss: 'virgo', likes: 'aries'},
  {ss: 'scorpio', likes: 'virgo'},
  {ss: 'cancer', likes: 'virgo'},
  {ss: 'sagitarius', likes: 'sagitarius'}
]

const CREATE_MATCH_ARRAY = () => {
	let matches = people.reduce((pre, person, i, orig) => {
  	pre.push([person, orig.find(p => person.likes === p.ss)])
    return pre
  }, [])
  
  return matches
}

console.log(CREATE_MATCH_ARRAY())

我可以看到的一个问题是你的people数组有唯一的标识符,这样如果一个人对象看起来像{ss: 'aries', likes: 'aries'}最终不会与自己匹配。

让我们看看我们能做些什么。

let people = [
	{ss: 'aries', likes: 'aries', ID: 1},
  {ss: 'cancer', likes: 'scorpio', ID: 2},
  {ss: 'virgo', likes: 'aries', ID: 3},
  {ss: 'scorpio', likes: 'virgo', ID: 4},
  {ss: 'cancer', likes: 'virgo', ID: 5},
	{ss: 'aries', likes: 'cancer', ID: 7},
  {ss: 'sagitarius', likes: 'sagitarius', ID: 6}
]

const CREATE_MATCH_ARRAY = () => {
	let matches = people.reduce((pre, person, i, orig) => {
  	pre.push([
      person, 
      orig
      .filter(p => p.ID !== person.ID)
      .find(p => person.likes === p.ss)])
    return pre
  }, [])
  
  return matches
}

console.log(CREATE_MATCH_ARRAY())

处理多个likes的代码

let people = [
	{ss: 'aries', likes: 'aries', ID: 1},
  {ss: 'cancer', likes: 'scorpio', ID: 2},
  {ss: 'virgo', likes: 'aries', ID: 3},
  {ss: 'scorpio', likes: ['virgo', 'aries', 'cancer'], ID: 4},
  {ss: 'cancer', likes: 'virgo', ID: 5},
	{ss: 'aries', likes: 'cancer', ID: 7},
  {ss: 'sagitarius', likes: 'sagitarius', ID: 6}
]

const CREATE_MATCH_ARRAY = () => {
	let matches = people.reduce((pre, person, i, orig) => {
  	let filteredOriginal = orig.filter(p => p.ID !== person.ID)
  	pre.push([
      person, 
      filteredOriginal
      .filter(p => p.ID !== person.ID)
      .filter(p => {
      	if (Array.isArray(person.likes)) {
        	return filteredOriginal.filter(p => person.likes.indexOf(p.ss) !== -1)
        }
        else {
        	return person.likes === p.ss      
        }
       })])
    return pre
  }, [])
  
  return matches
}

console.log(CREATE_MATCH_ARRAY())

1
投票

为什么不通过创建双向工作的方法来实现这一点?

const convertToArray = val => typeof val === 'string' ? [ val ] : val;

class Person {
  constructor(name, sign, compatibleSigns) {
    this.name = name;
    this.sign = sign;
    this.compatibleSigns = convertToArray(compatibleSigns);
  }
  likes(otherPerson) {
    if (otherPerson == null) {
      return false;
    }
    return this.compatibleSigns.indexOf(otherPerson.sign) > -1;
  }
  isLikedBy(otherPerson) {
    if (otherPerson == null || otherPerson.compatibleSigns == null) {
      return false;
    }
    return otherPerson.compatibleSigns.indexOf(this.sign) > -1;
  }
  isCompatible(otherPerson) {
    return this.likes(otherPerson) && this.isLikedBy(otherPerson);
  }
  likesSelf() {
    return this.likes(this);
  }
}

var a = new Person("Jim", "virgo", ["sagitarus", "piscis"]);
var b = new Person("Sara", "sagitarus", ["piscis", "sagitarus", "virgo"]);
var c = new Person("Sam", "aries", "Leo");

console.log(a.likes(b));        // True
console.log(a.isLikedBy(b));    // True
console.log(b.isCompatible(a)); // True
console.log(b.likesSelf());     // True
.as-console-wrapper { top: 0; max-height: 100% !important;}

0
投票

你可以使用find和filter来帮助,并检查两种方式的匹配。

这是一个例子:

    class Person {
        constructor(name, sign, likes) {
            this.name = name;
            this.sign = sign;
            this.likes = likes
        }
    }

    var a = new Person("Jim", "virgo", ["piscis"]);
    var b = new Person("Sara", "sagitarus", ["piscis", "sagitarus"]);
    var c = new Person("Sam", "piscis", ["sagitarus"]);

    var persons = [a, b, c];

    // helper methods
    var isLikedBy = function(person1, person2) {
      return person1.likes.indexOf(person2.sign) >= 0;
    };

    var findMatch = function(persons) {
      for(var x in persons) {
        var person = persons[x];
        var match = persons.find(function(p) {
          if(p == person) return false;
          return isLikedBy(person, p) && isLikedBy(p, person);
        });
        if(match) {
          return [person, match];
        }
      }
    }

    // find the match
    var match = findMatch(persons);
    if(match) {
      persons = persons.filter(function(p) {
        return match.indexOf(p) < 0;
      });
    }

    console.log(match, persons);
© www.soinside.com 2019 - 2024. All rights reserved.