过滤 javascript 中的对象数组,其中兄弟项匹配公共键值
filter an array of objects in javascript, with siblings that match on a common key value
假设我有一个 javascript 对象数组,如下所示:
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
]
现在,假设我有一个搜索字符串,例如“War”或“and”。我想获取一个对象数组,其中“title”包含搜索字符串(不区分大小写),但我还想包含任何具有匹配“copyversion”值的同级值。
例如:
“Great”的搜索字符串应该会产生以下结果,因为即使“History of World War II”中没有“Great”,它也与包含“Great”的内容的副本匹配。
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
}
]
另一个例子:
搜索字符串“Peace”将产生原始数组。收录《世界史WarII》是因为它与《太平盛世》具有相同的copyversion值,收录《罪与罚》是因为它与《War与和平》具有相同的copyversion “
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
]
如果未找到匹配项,则会生成一个空数组。
我正在寻找一种合理的快速方法来执行此操作。我可以使用纯 javascript 或像 lodash 这样的库。
解决方案包含两部分:
- 找到所有匹配的对象并收集它们的副本版本。不要重复存储。
- return 具有相应副本版本的所有对象。
可以优化第一部分 - 我们不必删除重复项。
const a = [
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
];
const copyFinder = (word, arr) => {
const rx = new RegExp(`${word}`, 'i');
const versions = arr.reduce((collector, value) => {
if(rx.test(value.title) && collector.indexOf(value.copyversion) === -1) {
collector.push(value.copyversion);
}
return collector;
}, []);
if(versions.length === 0) {
return [];
}
return arr.filter(x => versions.indexOf(x.copyversion) > -1);
}
console.log(copyFinder('History', a));
这是我的简单易读的解决方案。希望对你有用
const books = [
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
];
const findBooks = (titlePart) => {
const regexp = new RegExp(`${titlePart}`, 'i');
const resultSet = new Set();
const copyVersionsSet = new Set();
// Find all books which has titlePart in title
for (const book of books) {
if (regexp.test(book.title)) {
resultSet.add(book);
copyVersionsSet.add(book.copyversion);
}
}
// Find all books which has same copyversion as found books
for (const book of books) {
if (copyVersionsSet.has(book.copyversion)) {
resultSet.add(book);
}
}
return [...resultSet];
}
console.log(findBooks('hIsToRy'));
这是一种方法:
const findMatches = (books = []) => (
search = "",
lc = search .toLowerCase (),
matches = new Set (books .filter (({title}) => title .toLowerCase () .includes (lc))),
versions = new Set ([...matches] .map (({copyversion}) => copyversion))
) => books .filter ((book) => matches .has (book) || versions .has (book .copyversion))
const books = [{"title": "The Great Peace", "copyversion": 1}, {"title": "History of World War II", "copyversion": 1}, {"title": "Crime and Punishment", "copyversion": 2}, {"title": "War and Peace", "copyversion": 2}]
console .log ('crime: ', findMatches (books) ('crime'))
console .log ('great: ', findMatches (books) ('great'))
console .log ('war: ', findMatches (books) ('war'))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们采用 lower-case 版本的搜索字符串,使用它来过滤列表以找到具有匹配标题的列表,将它们存储为一个集合,然后将它们映射到它们的版本,再次存储为一个集合,最后将原始书籍列表过滤为 select 匹配集中的书籍或版本在第一版中的书籍。
虽然我选择以这种方式工作,在可行的情况下使用默认参数代替局部变量,但如果以某些方式使用 findMatches (books)
,则有可能 down-side,例如传递给 map
。如果这是一个问题,这个版本以稍微复杂的方式做同样的事情,没有那些潜在的问题,因为它知道的唯一参数是 books
和 search
:
const findMatches = (books = []) => (search = "") => ((
lc = search .toLowerCase (),
matches = new Set (books .filter (({title}) => title .toLowerCase () .includes (lc))),
versions = new Set ([...matches] .map (({copyversion}) => copyversion))
) => books .filter ((book) => matches .has (book) || versions .has (book .copyversion)))()
假设我有一个 javascript 对象数组,如下所示:
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
]
现在,假设我有一个搜索字符串,例如“War”或“and”。我想获取一个对象数组,其中“title”包含搜索字符串(不区分大小写),但我还想包含任何具有匹配“copyversion”值的同级值。
例如:
“Great”的搜索字符串应该会产生以下结果,因为即使“History of World War II”中没有“Great”,它也与包含“Great”的内容的副本匹配。
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
}
]
另一个例子:
搜索字符串“Peace”将产生原始数组。收录《世界史WarII》是因为它与《太平盛世》具有相同的copyversion值,收录《罪与罚》是因为它与《War与和平》具有相同的copyversion “
[
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
]
如果未找到匹配项,则会生成一个空数组。
我正在寻找一种合理的快速方法来执行此操作。我可以使用纯 javascript 或像 lodash 这样的库。
解决方案包含两部分:
- 找到所有匹配的对象并收集它们的副本版本。不要重复存储。
- return 具有相应副本版本的所有对象。
可以优化第一部分 - 我们不必删除重复项。
const a = [
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
];
const copyFinder = (word, arr) => {
const rx = new RegExp(`${word}`, 'i');
const versions = arr.reduce((collector, value) => {
if(rx.test(value.title) && collector.indexOf(value.copyversion) === -1) {
collector.push(value.copyversion);
}
return collector;
}, []);
if(versions.length === 0) {
return [];
}
return arr.filter(x => versions.indexOf(x.copyversion) > -1);
}
console.log(copyFinder('History', a));
这是我的简单易读的解决方案。希望对你有用
const books = [
{
"title": "The Great Peace",
"copyversion": 1
},
{
"title": "History of World War II",
"copyversion": 1
},
{
"title": "Crime and Punishment",
"copyversion": 2
},
{
"title": "War and Peace",
"copyversion": 2
}
];
const findBooks = (titlePart) => {
const regexp = new RegExp(`${titlePart}`, 'i');
const resultSet = new Set();
const copyVersionsSet = new Set();
// Find all books which has titlePart in title
for (const book of books) {
if (regexp.test(book.title)) {
resultSet.add(book);
copyVersionsSet.add(book.copyversion);
}
}
// Find all books which has same copyversion as found books
for (const book of books) {
if (copyVersionsSet.has(book.copyversion)) {
resultSet.add(book);
}
}
return [...resultSet];
}
console.log(findBooks('hIsToRy'));
这是一种方法:
const findMatches = (books = []) => (
search = "",
lc = search .toLowerCase (),
matches = new Set (books .filter (({title}) => title .toLowerCase () .includes (lc))),
versions = new Set ([...matches] .map (({copyversion}) => copyversion))
) => books .filter ((book) => matches .has (book) || versions .has (book .copyversion))
const books = [{"title": "The Great Peace", "copyversion": 1}, {"title": "History of World War II", "copyversion": 1}, {"title": "Crime and Punishment", "copyversion": 2}, {"title": "War and Peace", "copyversion": 2}]
console .log ('crime: ', findMatches (books) ('crime'))
console .log ('great: ', findMatches (books) ('great'))
console .log ('war: ', findMatches (books) ('war'))
.as-console-wrapper {max-height: 100% !important; top: 0}
我们采用 lower-case 版本的搜索字符串,使用它来过滤列表以找到具有匹配标题的列表,将它们存储为一个集合,然后将它们映射到它们的版本,再次存储为一个集合,最后将原始书籍列表过滤为 select 匹配集中的书籍或版本在第一版中的书籍。
虽然我选择以这种方式工作,在可行的情况下使用默认参数代替局部变量,但如果以某些方式使用 findMatches (books)
,则有可能 down-side,例如传递给 map
。如果这是一个问题,这个版本以稍微复杂的方式做同样的事情,没有那些潜在的问题,因为它知道的唯一参数是 books
和 search
:
const findMatches = (books = []) => (search = "") => ((
lc = search .toLowerCase (),
matches = new Set (books .filter (({title}) => title .toLowerCase () .includes (lc))),
versions = new Set ([...matches] .map (({copyversion}) => copyversion))
) => books .filter ((book) => matches .has (book) || versions .has (book .copyversion)))()