- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在客户端,我有一个复杂的 Javascript 对象可供使用。但当将其发送到服务器时,我只想发送其中的一部分。
我想克隆它,但只克隆我需要的部分。我想要一个可以实现类似功能的函数
var wireFriendly = reduce(original, "id, name, related.id, related.name");
// or
var wireFriendly = reduce(original, ["id", "name", "related.id", "related.name"]);
我已经创建了这个函数的大部分内容,当对象图仅由对象组成时,它可以满足我的要求。如果我里面有数组,它就不起作用。但这是我到目前为止得到的:
function (entity, keepMembersList) {
// check entity that it's not undefined, null and that it's an actual Object instance
if (Object.prototype.toString.call(entity) !== "[object Object]")
{
throw "'entity' parameter should be a non-null object."
}
// code in switch statement only normalizes function arguments when
// they are provided either as a string or as an array of string
switch (Object.prototype.toString.call(keepMembersList))
{
case '[object String]':
keepMembersList = keepMembersList.split(',').map(function (value) {
return value.trim();
});
case '[object Array]':
keepMembersList = keepMembersList.map(function (value) {
return value.split(".");
});
break;
default:
throw "Parameter 'keepMembersList' should either be a comma delimited list of members' names to keep or an array of them.";
}
// from this point on, cloning is taking place
var result = {};
for (var i = 0; i < keepMembersList.length; i++)
{
for (var j = 0, r = result, e = entity; j < keepMembersList[i].length - 1; j++)
{
// ----------------------------------------------------------
// this part should be changed to also detect array notations
// ----------------------------------------------------------
r = r[keepMembersList[i][j]] = r[keepMembersList[i][j]] || {};
e = e[keepMembersList[i][j]];
}
r[keepMembersList[i][j]] = e[keepMembersList[i][j]];
}
return result;
}
我希望它也适用于这几个示例
// clone all array elements with specific members
var wireFriendly = reduce(original, "id, name, related[].id, related[].name");
// clone specific array element with specific members
var wireFriendly = reduce(original, ["id", "name", "related[0].id", "related[0].name"]);
但我至少可以接受第一个示例,其中数组的所有元素都被成员缩减。仅克隆特定数组元素的第二个示例对于我的情况来说并不重要,但我认为拥有它也很棒。当然,在这种情况下,结果数组上的索引不必匹配,否则我们会遇到未定义的元素:
//in case related[3].id would be specified we'd end up with
related:[undefined, undefined, undefined, { id: 1 }];
使用该对象作为需要部分克隆的原始实体:
var original = {
"related":[{
"related":[],
"id":1759807323,
"name":"Related name",
"interest":{
"id":1314962015,
"name":"Ideas",
"isLocked":false,
"isPrivileged":false
},
"details":"Lengthy related details that will not be sent to server"
}],
"name":"My name",
"interest":{
"id":1314962015,
"name":"Ideas",
"isLocked":false,
"isPrivileged":false
},
"details":"Some lengthy details"
}
您可以使用 this JSFiddle 中的此函数测试工作示例.
最佳答案
我提供自己的答案以供将来引用。最终的解决方案分为两步:
请注意,这会创建原始对象的简化浅拷贝,因为我不会进一步操作它来意外更改原始对象。如果您需要克隆,您可以通过检测日期、正则表达式和其他实际需要创建新实例的内容,向展平
或取消展平
函数添加附加功能。
测试对象(问题上方)在展平后看起来像这样:
var flattened = {
"name": "My name",
"details": "Some lengthy details",
"interest.id": 1314962015,
"interest.name": "Ideas",
"interest.isLocked": false,
"interest.isPrivileged": false,
"related[0].related": [],
"related[0].id": 1759807323,
"related[0].name": "Related name",
"related[0].interest.id": 1314962015,
"related[0].interest.name": "Ideas",
"related[0].interest.isLocked": false,
"related[0].interest.isPrivileged": false,
"related[0].details": "Lengthy related details that will not be sent to server"
};
属性被重命名以表示多级对象。
我尝试了几种不同的版本,从使用堆栈迭代到递归。这个表现最好。
// "keep" is a HashMap-like object detailed later
function flatten(obj, keep) {
// normalize parameters
keep = keep || { contains: function () { return true; } };
var result = {};
var traverse = function (current, prefix) {
switch (Object.prototype.toString.call(current))
{
case "[object Object]":
for (var prop in current)
{
traverse(current[prop], (prefix.length ? prefix + "." : "") + prop);
}
// when there were no properties it's an empty object instance
if (!prop && keep.contains(prefix))
{
result[prefix] = {};
}
break;
case "[object Array]":
// arrays
for (var i = 0, l = current.length; i < l; i++)
{
traverse(current[i], (prefix.length ? prefix : "") + "[" + i + "]");
}
// when there were no elements it's an empty array instance'
if (l === 0 && keep.contains(prefix))
{
result[prefix] = [];
}
break;
case "[object Null]":
case "[object Undefined]":
case "[object Function]":
// don't use nulls, undefineds or functions
break;
default:
// primitive values: string, number, boolean, date, regexp
if (keep.contains(prefix))
{
result[prefix] = current;
}
}
};
traverse(obj, "");
return result;
};
最快的反扁平化是使用 indexOf
和 substring
函数而不是 split
并迭代生成的数组。
// "obj" is a flattened object instance
var unflatten = function unflatten(obj) {
var result = {},
current,
prop,
currIdx,
normalized;
for (var props in obj)
{
normalized = props.replace(/\[(\d+)\]/gi, ".$1");
current = result;
currIdx = -2;
while (currIdx !== -1)
{
prop = normalized.substring(
++currIdx,
(currIdx = normalized.indexOf(".", currIdx)) !== -1 ? currIdx : undefined
);
if (currIdx > 0)
{
current = current[prop] || (current[prop] = isNaN(parseInt(normalized.substring(currIdx + 1))) ? {} : []);
}
}
current[prop] = obj[props];
}
return result;
};
正如您在 flatten
函数中看到的,keep
参数的类型为 HashMap
,具有 contains
函数。当您不提供任何 keep
参数时,flatten
将保留所有属性,因此默认 keep
实例位于函数开头。
var hashMapRx = /\[\d*\]/gi;
// Fast dictionary-like searching
var HashMap = function constructor(stringArray) {
this.hash = {};
for (var i = 0, l = stringArray.length; i < l; i++)
{
this.hash[this.normalize(stringArray[i])] = true;
}
};
HashMap.prototype.contains = function contains(value) {
var val = this.normalize(value);
return !!this.hash[val] || this.any(val);
};
HashMap.prototype.normalize = function normalize(value) {
return value.replace(hashMapRx, "[]");
};
HashMap.prototype.any = function any(value) {
var result = false;
for (var key in this.hash)
{
if (value === key || value.substr(0, key.length) === key)
return true;
}
return false;
};
实例化HashMap
并提供以下形式的字符串数组时
["id", "name", "addresses[0].street", "addresses[].country" ...]
这些名称已标准化。我特意在这里提供了一个带有数组索引 (0
) 的属性,而另一个则没有。它们都被标准化为没有索引的版本。因此,当发生展平时,所有数组项都会根据其属性定义包含在内。
减少变得像调用一样简单:
var reducedObj = unflatten(flatten(obj, keep));
关于javascript - 高级 JavaScript : Partial cloning of an object graph,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27401063/
对于相当简单的表结构,即。人员、标准和 PersonCriteria(组合表),我现在设置了一个查询,选择所有符合所有选定条件的人。 此时查询本身看起来像这样: SELECT p.PersonID
我在使用高级 SQL 查询时遇到了一些问题,而且我已经有很长时间没有使用 SQL 数据库了。我们使用 MySQL。 背景: 我们将使用两个表: “交易表” 表:expire_history +----
我找不到错误。也许你可以帮助我:我的代码如下: var data = {"product":[{"config":[{"id":"1","price":"100","sku":"1054879634
我有一个列表列表的列表(最后一个列表并不重要) data = [[[['f', 0], 'C'], [['X', 0], 'X']], [[['s', 1], 'X'], [['X', 0], 'X'
我想准备将使用表格的 session ,并在另一个网站上将新项目添加到 session 中。 默认.cs string[] tab = new string[100];
我知道有一些像: Bubble sort Insertion sort Shell sort Merge sort Heapsort Quicksort Bucket sort Radix sort
像https://softwareengineering.stackexchange.com/questions/150616/return-random-list-item-by-its-weigh
我正在开发一个 posix 脚本 (Linux),它获取一个网页,将内容存储在一个变量中并查找字符串“SUCCESS”。如果找到字符串,则不执行循环内容,如果没有找到字符串,则反复执行循环,直到找到为
我不确定这个问题是否已在其他地方得到解答,而且我似乎无法通过谷歌找到任何不是“Hello World”示例的内容...我正在使用 C# .NET 4.0 进行编码。 我正在尝试开发一个控制台应用程序,
我创建了一个房地产网站,我希望按照列表的最后更新和完整性对列表进行排序。所以我一直想弄清楚如何结合最近更新的列表按mysql中的字段(completion_score)进行排序。完成分数将采用 1
只所以称为“高级”用法,是因为我连switch的最基础的用法都还没有掌握,so,接下来讲的其实还是它的基础用法! switch 语句和具有同样表达式的一系列的 IF 语句相似。很多场合下需要把同一
之前的章节中,我们学习了 XML DOM,并使用了 XML DOM 的 getElementsByTagName() 方法从 XML 文档中取回数据 本章节我们将继续学习其它重要的 XML DOM
我对我尝试编写的 SQL 查询有疑问。 我需要从数据库中查询数据。该数据库除其他外,还包括以下 3 个字段: Account_ID #, Date_Created, Time_Created 我需要编
我正在使用非常激进的视频压缩,例如 -crf 51 .我将其用于“艺术”效果,因此从普通视频压缩的角度来看,我所做的可能没有意义。 到目前为止,我只使用了非常基本的压缩控制,只使用了 -crf。或 -
我真的在学习 lucene 和 ravendb 上的绳索 - 我在 Raven 中有以下文档 - { "InternalEvent": { "Desec": "MachineInfo: 1
通常 grep 命令用于显示包含指定模式的行。有没有办法在包含指定模式的行之前和之后显示 n 行? 这可以使用awk来实现吗? 最佳答案 是的,使用 grep -B num1 -A num2 在匹配之
我搜索了高低,并尝试了几个小时来操纵似乎适合的各种其他查询,但我没有快乐。 我试图加入 Microsoft SQL Server 2005 中的几个表,其中一个示例是: Company Table (
我有一个如下所示的 XML 文件: teacher1Name
我将如何在 CF 中创建此语句? 显然括号不起作用,但说明了我想要完成的工作。这是什么语法? 编辑: 好的,我了解如何使用 EQ 等等。我有点匆忙地发布了这个。我的问题是关于括号。以这种方式使用它们
主要问题:我需要使用具体对象结构对任何对象结构进行类型扩展。 我在 VS Code 中测试的默认值。 我的解决方案: /** @template A @typedef {{[Ki in keyof A
我是一名优秀的程序员,十分优秀!