过滤 JavaScript 中的对象数组,其中的同级对象与公共键值匹配

发布于 2025-01-12 14:39:46 字数 1289 浏览 2 评论 0原文

假设我有一个 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”字符串将产生原始数组。包含“二战史”是因为它与“伟大和平”具有相同的副本版本值,并且包含“罪与罚”是因为它与“战争与和平”具有相同的副本版本

[
    {
        "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 这样的库很满意。

Suppose I have a javascript array of objects that looks like this:

[
    {
        "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
    }
]

Now, suppose that I have a search string, like "War" or "and". I want to get an array of objects where "title" contains the search string (case insensitive), but I want to ALSO include any sibling values with matching "copyversion" values.

For example:

Search string of "Great" should yield the below result, because even though "History of World War II" does not have "Great" in it, it matches the copyversion of something that does.

[
    {
        "title": "The Great Peace",
        "copyversion": 1
    },
    {
        "title": "History of World War II",
        "copyversion": 1
    }
]

Another example:

Search string of "Peace" would yield the original array. "History of World War II" is included because it has the same copyversion value as "The Great Peace", and "Crime and Punishment" is included because it has the same copyversion as "War and Peace"

[
    {
        "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
    }
]

If no matches are found, then an empty array would result.

I'm looking for a reasonable fast way to do this. I'm fine with pure javascript or a library like lodash.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

阳光下的泡沫是彩色的 2025-01-19 14:39:46

解决方案包含两部分:

  1. 查找所有匹配的对象并收集它们的副本版本。不要存储重复项。
  2. 返回具有相应副本版本的所有对象。

第一部分可能会被优化 - 我们不必删除重复项。

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));

Solution contains two parts:

  1. find all matching objects and collect their copyversion. Do not store duplicates.
  2. return all objects with the corresponding copyversion.

The first part may be optimized - we don't have to remove duplicates.

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));

毁我热情 2025-01-19 14:39:46

这是我的简单易读的解决方案。希望它对你有用

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'));

That is my simple and readable solution. Hope it will useful for you

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'));

冷…雨湿花 2025-01-19 14:39:46

这是一种方法:

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}

我们采用搜索字符串的小写版本,用它来过滤列表以找到具有匹配标题的列表,将它们存储为 Set,然后将它们映射到其版本,再次存储为 Set,最后过滤原始列表书籍来选择匹配集中的书籍或其版本在版本一中的书籍。

尽管我选择以这种方式工作,但在可行的情况下使用默认参数代替局部变量,但如果以某些方式使用 findMatches (books) ,例如被传递,则存在潜在的缺点到地图。如果这是一个问题,这个版本会以稍微复杂的方式做同样的事情,没有这些潜在的问题,因为它知道的唯一参数是 bookssearch

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)))()

Here's one approach:

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}

We take the lower-case version of the search string, use that to filter the list to those with matching titles, storing them as a Set, then mapping them to their versions, again storing as a Set, and finally filter the original list of books to select those in that matches set or whose versions are in the version one.

Although I choose to work in this style, using defaulted parameters in place of local variables when feasible, there is a potential down-side, if findMatches (books) is used in certain ways, such as being passed to map. If that's a concern, this version does the same thing in a slightly more complex manner, without those potential problems, as the only parameters it knows about are books and 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)))()
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文