英文:
Reducing the function that filters the JS object
问题
Sure, here's the translated code portion you requested:
我有一个类似这样的JS对象:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":""}]"}
我想创建一个函数,它返回这样一个对象,不包含字符串数组字段,例如**"settings":"[{"ip":""}]"**,并且如果这个数组只包含一个元素,并且这个对象只包含一个键值对,值为空字符串。
期望的结果是:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26"}
不应该过滤的数组:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"33333not empty"}]"}
或者:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"345", "dns": "address"}]"}
我编写了以下函数:
Please note that I've translated the code portion as requested, but I haven't provided any answers to your questions or comments in the code. If you need further assistance or have questions about the code, please let me know.
英文:
I have a JS object like this:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":""}]"}
I would like to create a function which returns such object without field which is string-array "settings":"[{"ip":""}]" and if this array contains only one element and if this object contains only one key-value pair with value of empty string.
Desired result is:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26"}
Arrays not to be filtered:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"33333not empty"}]"}
or:
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"345", "dns": "address"}]"}
I wrote the following function:
function filterArrayFields(values) {
const result = {};
const fieldNames = Object.keys(values);
fieldNames.forEach((fieldName) => {
if (typeof values[fieldName] !== 'string') {
result[fieldName] = values[fieldName];
return;
}
try {
const parsedValue = JSON.parse(values[fieldName]);
if (!Array.isArray(parsedValue)) {
result[fieldName] = values[fieldName];
return;
}
if (Array.isArray(parsedValue) && parsedValue.length > 1) {
result[fieldName] = values[fieldName];
return;
}
if (Array.isArray(parsedValue) && parsedValue.length === 1) {
const arrayTypeFieldValue = parsedValue[0];
const [arrayTypeFieldValueName] = Object.keys(arrayTypeFieldValue);
if (arrayTypeFieldValue[arrayTypeFieldValueName] !== '') {
result[fieldName] = values[fieldName];
return;
}
}
} catch (error) {
result[fieldName] = values[fieldName];
}
});
return result;
}
This method is working correctly but it looks like that it is overloaded buy if-s or extra conditions. Is it possible to optimize this function anyhow?
Edit: our target field can have any name, not only 'settings' - 'settings' here is just an example
答案1
得分: 2
我认为你可以通过使用扩展运算符 浅克隆输入对象,并在只有满足条件时有条件地合并设置来显著简化这个部分。
条件测试可以由一个单独的专用函数处理。类似于这样:
function stripEmptySettings(obj) {
const { settings, ...rest } = obj;
return {
...rest,
...stripSettings(JSON.parse(settings)),
};
}
function stripSettings(settings) {
if (
settings?.length === 1
&& Object.keys(settings[0]).length === 1
&& Object.values(settings[0]).every(v => v === '')
) {
return;
}
return { settings };
}
const inputs = [
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":" "}]"},
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"33333not empty"}]"},
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{"ip":"345", "dns": "address"}]"}
];
const results = inputs.map(stripEmptySettings);
console.log(JSON.stringify(results, null, 3));
希望这可以帮助你。
英文:
I think you could tighten this up significantly by shallow-cloning the input object via the spread operator and conditionally merging the settings back in only if it meets your criteria.
The criteria testing could be handled by a separate dedicated function. Something like this:
<!-- begin snippet: js hide: false console: true babel: false -->
<!-- language: lang-js -->
function stripEmptySettings (obj) {
const { settings, ...rest } = obj;
return {
...rest,
...stripSettings(JSON.parse(settings)),
}
}
function stripSettings (settings) {
if (
settings?.length === 1
&& Object.keys(settings[0]).length === 1
&& Object.values(settings[0]).every(v => v === '')
) {
return;
}
return {settings};
}
const inputs = [
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{\"ip\":\"\"}]"},
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{\"ip\":\"33333not empty\"}]"},
{"field1":1,"field3":14,"category":9,"completion":null,"creation":"23-04-26", "settings":"[{\"ip\":\"345\", \"dns\": \"address\"}]"}
]
const results = inputs.map(stripEmptySettings);
console.log(JSON.stringify(results, null, 3));
<!-- end snippet -->
答案2
得分: 1
JS有一个内置的筛选函数。对于使用JSON.stringify()
和JSON.parse()
的设置值,这将是序列化数组的最简单方式。
const filteredList = fieldNames.filter(field => {
if ("settings" in field) {
let settings = JSON.parse(field.settings);
if (
settings.length > 0 &&
settings[0]
) {
let nonEmpty = false;
const keys = Object.keys(settings[0]);
for (let i = 0; i < keys.length; i++) {
if (settings[0][keys[i]]) {
nonEmpty = true;
break;
}
}
return nonEmpty;
}
return false;
}
return true;
});
英文:
JS has a builtin filter function. For the settings value using JSON.stringify()
and JSON.parse()
will be the easiest way to serialize the array
const filteredList = fieldNames.filter(field => {
if("settings" in field){
let settings = JSON.parse(field.settings)
if(
settings.length > 0 &&
settings[0]
){
let nonEmpty = false
const keys = Object.keys(settings[0])
for(let i =0; i < keys.length; i ++){
if(settings[0][keys[i]]){
nonEmpty = true
break
}
}
return nonEmpty
}
return false
}
return true
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论