假设我有一个人类
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, ....]
我想要实现的是,从数组的开始,根据他们的符号和他们感兴趣的内容找到第一个可能的匹配。
例如:
我期望得到的是:
像这样的东西:
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
在这里,我们减少你的数组,并找到一个匹配基于原始阵列的星号(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())
为什么不通过创建双向工作的方法来实现这一点?
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;}
你可以使用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);