- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
TL; 博士;
为简单起见,我如何过滤父子数组的多个属性,这些属性可能是几个树级别的深度。这是针对数百个用户使用的开源数据网格库。
所以我有一系列父/子引用, children 也可以有 child 自己等等,树级深度没有限制。此外,我不仅需要能够过滤具有树结构的属性,还需要能够过滤该数组的任何属性,即网格中的列。
例如,我有这个数组,它代表一个文件浏览器列表
const myFiles = [
{id: 11, file: "Music", parentId: null },
{id: 12, file: "mp3", parentId: 11 },
{id: 14, file: "pop", parentId: 12 },
{id: 15, file: "theme.mp3", dateModified: "2015-03-01", size: 85, parentId: 14, },
{id: 16, file: "rock", parentId: 12 },
{id: 17, file: "soft.mp3", dateModified: "2015-05-13", size: 98, parentId: 16, },
{id: 18, file: "else.txt", dateModified: "2015-03-03", size: 90, parentId: null, },
{id: 21, file: "Documents", parentId: null, },
{id: 2, file: "txt", parentId: 21 },
{id: 3, file: "todo.txt", dateModified: "2015-05-12", size: 0.7, parentId: 2, },
{id: 4, file: "pdf", parentId: 21 },
{id: 22, file: "map2.pdf", dateModified: "2015-05-21", size: 2.9, parentId: 4 },
{id: 5, file: "map.pdf", dateModified: "2015-05-21", size: 3.1, parentId: 4, },
{id: 6, file: "internet-bill.pdf", dateModified: "2015-05-12", size: 1.4, parentId: 4, },
{id: 7, file: "xls", parentId: 21 },
{id: 8, file: "compilation.xls", dateModified: "2014-10-02", size: 2.3, parentId: 7, },
{id: 9, file: "misc", parentId: 21 },
{id: 10, file: "something.txt", dateModified: "2015-02-26", size: 0.4, parentId: 9, },
]
{id: 21, file: "Documents", parentId: null, treeMap: ["Documents", "PDF", "map.pdf"] }
{id: 4, file: "pdf", parentId: 21, treeMap: ["PDF", "map.pdf"] }
{id: 5, file: "map.pdf", dateModified: "2015-05-21", size: 3.1, parentId: 4, treeMap: ["map.pdf"] }
export function modifyDatasetToAddTreeMapping(items: any[], treeViewColumn: Column, dataView: any) {
for (let i = 0; i < items.length; i++) {
items[i]['treeMap'] = [items[i][treeViewColumn.id]];
let item = items[i];
if (item['parentId'] !== null) {
let parent = dataView.getItemById(item['parentId']);
while (parent) {
parent['treeMap'] = dedupePrimitiveArray(parent['treeMap'].concat(item['treeMap']));
item = parent;
parent = dataView.getItemById(item['parentId']);
}
}
}
}
export function dedupePrimitiveArray(inputArray: Array<number | string>): Array<number | string> {
const seen = {};
const out = [];
const len = inputArray.length;
let j = 0;
for (let i = 0; i < len; i++) {
const item = inputArray[i];
if (seen[item] !== 1) {
seen[item] = 1;
out[j++] = item;
}
}
return out;
}
columnFilters
是一个包含 1 个或多个过滤器的对象,例如
const columnFilters = { file: 'map', size: '>3' }
dataView.setFilter(treeFilter);
function treeFilter(dataView: any, item: any) {
const columnFilters = { file: this.searchString.toLowerCase(), size: 2 };
let filterCount = 0;
if (item[parentPropName] !== null) {
let parent = dataView.getItemById(item['parentId']);
while (parent) {
if (parent.__collapsed) {
return false;
}
parent = dataView.getItemById(parent['parentId']);
}
}
for (const columnId in columnFilters) {
if (columnId !== undefined && columnFilters[columnId] !== '') {
filterCount++;
if (item.treeMap === undefined || !item.treeMap.find((itm: string) => itm.endsWith(columnFilters[columnId]))) {
return false;
}
}
}
return true;
}
modifyDatasetToAddTreeMapping()
的电话如果我想在 File 列上过滤它可以正常工作,但是如果我添加更多列过滤器,它就不能按预期工作。例如,如果您查看第二个打印屏幕,您会看到我输入了“map”,它将显示“Documents > PDF > map.pdf”,这很好,但是如果添加的文件大小小于 3Mb,则应该't 显示“map.pdf”,并且因为该文件未显示并且“文档> PDF”不包含“ map ”一词,因此不应显示任何内容,因此您可以看到过滤器的行为不正常。
modifyDatasetToAddTreeMapping()
是一个可能不需要的额外调用
filter
,这意味着最终的解决方案将是一种方法
myFilter
那将是
filter
回调方法。我坚持这个的原因是因为我使用了一个外部库
SlickGrid并且我必须使用该库中可用的内容作为公开的公共(public)方法。
function myFilter(item, args) {
const columnFilters = args.columnFilters;
// iterate through each items of the dataset
// return true/false on each item
}
// to be used as a drop in
dataView.setFilterArgs({ columnFilters: this._columnFilters });
dataView.setFilter(myFilter.bind(this));
const columnFilters = { file: "map", size: "<3.2" };
,数组的预期结果将是 4 行
// result
[
{id: 21, file: "Documents", parentId: null },
{id: 4, file: "pdf", parentId: 21, },
{id: 22, file: "map2.pdf", dateModified: "2015-05-21", size: 2.9, parentId: 4 },
{id: 5, file: "map.pdf", dateModified: "2015-05-21", size: 3.1, parentId: 4, }
]
const columnFilters = { file: "map", size: "<3" };
,数组的预期结果将是 3 行
// result
[
{id: 21, file: "Documents", parentId: null },
{id: 4, file: "pdf", parentId: 21, },
{id: 22, file: "map2.pdf", dateModified: "2015-05-21", size: 2.9, parentId: 4 },
]
const columnFilters = { file: "map", size: ">3" };
那么预期的结果将是一个空数组,因为没有一个文件具有该字符和文件大小条件。
最佳答案
我有办法做到这一点。它应该具有相当的性能,但我们可能还想将 map 和 reduce 等替换为旧的 for 循环以进一步优化速度(我看过各种博客和文章,比较了 forEach、map 等与 for 循环和 for 的速度) -循环似乎赢了)
这是一个演示(也在这里: https://codepen.io/Alexander9111/pen/abvojzN ):
const myFiles = [
{ id: 11, file: "Music", parentId: null },
{ id: 12, file: "mp3", parentId: 11 },
{ id: 14, file: "pop", parentId: 12 },
{ id: 15, file: "theme.mp3", dateModified: "2015-03-01", size: 85, parentId: 14 },
{ id: 16, file: "rock", parentId: 12 },
{ id: 17, file: "soft.mp3", dateModified: "2015-05-13", size: 98, parentId: 16 },
{ id: 18, file: "else.txt", dateModified: "2015-03-03", size: 90, parentId: null },
{ id: 21, file: "Documents", parentId: null },
{ id: 2, file: "txt", parentId: 21 },
{ id: 3, file: "todo.txt", dateModified: "2015-05-12", size: 0.7, parentId: 2 },
{ id: 4, file: "pdf", parentId: 21 },
{ id: 22, file: "map2.pdf", dateModified: "2015-05-21", size: 2.9, parentId: 4 },
{ id: 5, file: "map.pdf", dateModified: "2015-05-21", size: 3.1, parentId: 4 },
{ id: 6, file: "internet-bill.pdf", dateModified: "2015-05-12", size: 1.4, parentId: 4 },
{ id: 7, file: "xls", parentId: 21 },
{ id: 8, file: "compilation.xls", dateModified: "2014-10-02", size: 2.3, parentId: 7 },
{ id: 9, file: "misc", parentId: 21 },
{ id: 10, file: "something.txt", dateModified: "2015-02-26", size: 0.4, parentId: 9 }
];
//example how to use the "<3" string - better way than using eval():
const columnFilters = { file: "map", size: "<3.2" }; //, size: "<3"
const isSizeValid = Function("return " + myFiles[11].size + "<3")();
//console.log(isSizeValid);
const myObj = myFiles.reduce((aggObj, child) => {
aggObj[child.id] = child;
//the filtered data is used again as each subsequent letter is typed
//we need to delete the ._used property, otherwise the logic below
//in the while loop (which checks for parents) doesn't work:
delete aggObj[child.id]._used;
return aggObj;
}, {});
function filterMyFiles(myArray, columnFilters){
const filteredChildren = myArray.filter(a => {
for (let key in columnFilters){
//console.log(key)
if (a.hasOwnProperty(key)){
const strContains = String(a[key]).includes(columnFilters[key]);
const re = /(?:(?:^|[-+<>=_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-<>=]?\d+)?\s*))+$/;
const comparison = re.test(columnFilters[key]) && Function("return " + a[key] + columnFilters[key])();
if (strContains || comparison){
//don't return true as need to check other keys in columnFilters
}else{
//console.log('false', a)
return false;
}
} else{
return false;
}
}
//console.log('true', a)
return true;
})
return filteredChildren;
}
const initFiltered = filterMyFiles(myFiles, columnFilters);
const finalWithParents = initFiltered.map(child => {
const childWithParents = [child];
let parent = myObj[child.parentId];
while (parent){
//console.log('parent', parent)
parent._used || childWithParents.unshift(parent)
myObj[parent.id]._used = true;
parent = myObj[parent.parentId] || false;
}
return childWithParents;
}).flat();
console.log(finalWithParents)
.as-console-wrapper { max-height: 100% !important; top: 0; }
const myFiles = [
{ id: 11, file: "Music", parentId: null },
{ id: 12, file: "mp3", parentId: 11 },
{ id: 14, file: "pop", parentId: 12 },
{ id: 15, file: "theme.mp3", dateModified: "2015-03-01", size: 85, parentId: 14 },
{ id: 16, file: "rock", parentId: 12 },
{ id: 17, file: "soft.mp3", dateModified: "2015-05-13", size: 98, parentId: 16 },
{ id: 18, file: "else.txt", dateModified: "2015-03-03", size: 90, parentId: null },
{ id: 21, file: "Documents", parentId: null },
{ id: 2, file: "txt", parentId: 21 },
{ id: 3, file: "todo.txt", dateModified: "2015-05-12", size: 0.7, parentId: 2 },
{ id: 4, file: "pdf", parentId: 21 },
{ id: 22, file: "map2.pdf", dateModified: "2015-05-21", size: 2.9, parentId: 4 },
{ id: 5, file: "map.pdf", dateModified: "2015-05-21", size: 3.1, parentId: 4 },
{ id: 6, file: "internet-bill.pdf", dateModified: "2015-05-12", size: 1.4, parentId: 4 },
{ id: 7, file: "xls", parentId: 21 },
{ id: 8, file: "compilation.xls", dateModified: "2014-10-02", size: 2.3, parentId: 7 },
{ id: 9, file: "misc", parentId: 21 },
{ id: 10, file: "something.txt", dateModified: "2015-02-26", size: 0.4, parentId: 9 }
];
const columnFilters = { file: "map", size: "<3.2" };
console.log(customLocalFilter(myFiles, columnFilters));
function customLocalFilter(array, filters){
const myObj = {};
for (let i = 0; i < myFiles.length; i++) {
myObj[myFiles[i].id] = myFiles[i];
//the filtered data is used again as each subsequent letter is typed
//we need to delete the ._used property, otherwise the logic below
//in the while loop (which checks for parents) doesn't work:
delete myObj[myFiles[i].id]._used;
}
const filteredChildrenAndParents = [];
for (let i = 0; i < myFiles.length; i++) {
const a = myFiles[i];
let matchFilter = true;
for (let key in columnFilters) {
if (a.hasOwnProperty(key)) {
const strContains = String(a[key]).includes(columnFilters[key]);
const re = /(?:(?:^|[-+<>!=_*/])(?:\s*-?\d+(\.\d+)?(?:[eE][+-<>!=]?\d+)?\s*))+$/;
const comparison =
re.test(columnFilters[key]) &&
Function("return " + a[key] + columnFilters[key])();
if (strContains || comparison) {
//don't return true as need to check other keys in columnFilters
} else {
matchFilter = false;
continue;
}
} else {
matchFilter = false;
continue;
}
}
if (matchFilter) {
const len = filteredChildrenAndParents.length;
filteredChildrenAndParents.splice(len, 0, a);
let parent = myObj[a.parentId] || false;
while (parent) {
//only add parent if not already added:
parent._used || filteredChildrenAndParents.splice(len, 0, parent);
//mark each parent as used so not used again:
myObj[parent.id]._used = true;
//try to find parent of the current parent, if exists:
parent = myObj[parent.parentId] || false;
}
}
}
return filteredChildrenAndParents;
}
.as-console-wrapper { max-height: 100% !important; top: 0; }
关于javascript - 如何过滤可能是几个树级别深度的父子数组的多个属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61034229/
场景 网站页面有一个带有分页、过滤、排序功能的表格 View 。 表中的数据是从REST API服务器获取的,数据包含数百万条记录。 数据库 REST API 服务器 Web 服务器 浏览器 问
我有一个表student,其中的列dte_date(日期)具有值(2019-01-01、2019-02-01、2019-03-01)。 .等) 条件: dte_date 列中没有重复值。 但 dte_
我有一些逻辑可以根据不活动的用户创建通知。我正在获取具有以下属性的用户列表。我想做的只是在部门有非 Activity 用户时触发我的创建通知方法。因此,给出下面的列表,基本上会创建 1 个通知,表示部
使用 GPS 开发跟踪应用程序。一切都很好,但有时由于封闭区域或恶劣天气,我得到的分数不准确。当您绘制它们时,它看起来不对,有很多跃点/跳跃。 我应该运行什么算法来过滤掉不良信号对我来说,这看起来像是
我正在尝试按变量类型过滤对象数组。节点是一个具有位置的对象,但以不同的方式定义——作为点、矢量或附件。这是一个代码: class Joint { var position:Position
我想做的是在向量上创建一个过滤器,以便它删除未通过谓词测试的元素;但不太确定我该怎么做。 我根据谓词评估输入向量中的每个元素,例如在我的代码中,is_even 仿函数在 device_vector 向
我是 Gremlin 的新手,我正在使用 Gremlin 3.0.2 和 Stardog 5.0。我编写此查询是为了找出 schema.org 本体中两个实体之间的路径。以下是输出 - gremlin
考虑以下示例数据表, dt 30 的那一行需要去 - 或者如果其中两行 > 30相隔几秒钟,删除所有 3 个。然而 ,当我们有 4 行或更多行时,我们需要删除时间差 > 30 没有另一对 < 30
我正在考虑使用 ZeroMQ,并尝试了一些示例。但是,我无法验证 ZeroMQ 是否支持一些重要的要求。我希望你能帮助我。 我将使用这个简单的场景来问我的问题: 出版商(例如交易所)提供(大量)股票的
我需要从我的查询中过滤掉大量的对象。目前,它正在抓取类中的所有对象,我想将其过滤为查询字符串中的相关对象。我怎样才能做到这一点?当我尝试时,我收到一个属性错误说明 ''QuerySet' object
如何在 Prometheus 查询中添加标签过滤器? kube_pod_info kube_pod_info{created_by_kind="ReplicaSet",created_by_name=
我有包含字符串的列的数据框,并希望过滤掉包含某些字符串以外的任何内容的所有行。考虑下面的简化示例: string % dplyr::filter(stringr::str_detect(string,
我有以下数据框,其中包含多行的角度变化值: 'data.frame': 712801 obs. of 4 variables: $ time_passed: int 1 2 3 4 5 6
我有一个 BehaviorSubject我希望能够filter ,但要保持新订阅者在订阅时始终获得一个值的行为主题式质量,即使最后发出的值被过滤掉。有没有一种简洁的方法可以使用 rxjs 的内置函数来
我有一个 RSS 提要,每天输出大约 100 篇文章。我希望过滤它以仅包含更受欢迎的链接,也许将其过滤到 50 个或更少。回到当天,我相信您可以使用“postrank”来做到这一点,但在谷歌收购后现已
我有这样一个重复的xml树- this is a sample xml file yellowred blue greyredblue 如您所见,每个项目可以具有不同数量的颜色标签
我以为我在 Haskell 学习中一帆风顺,直到... 我有一个 [[Int]] tiles = [[1,0,0] ,[0,1,0] ,[0,1,0]
我在使用 Knockout.js 过滤可观察数组时遇到问题 我的js: 包含数据的数组 var docListData = [ { name: "Article Name 1", info:
我在 mongoDB 中有这个架构: var CostSchema = new Schema({ item: String, value: Number }); var Attachm
给定一个数据框“foo”,我如何才能只选择“foo”中的那些行,例如foo$location =“那里”? foo = data.frame(location = c("here", "there",
我是一名优秀的程序员,十分优秀!