我有一个扁平的JS对象:
{a: 1, b: 2, c: 3, ..., z:26}
我想克隆除一个元素之外的对象:
{a: 1, c: 3, ..., z:26}
最简单的方法是什么(如果可能,最好使用es6 / 7)?
答案 0 :(得分:277)
如果您使用Babel,则可以使用以下语法将属性b从x复制到变量b,然后将其余属性复制到变量y :
let x = {a: 1, b: 2, c: 3, z:26};
let {b, ...y} = x;
"use strict";
function _objectWithoutProperties(obj, keys) { var target = {}; for (var i in obj) { if (keys.indexOf(i) >= 0) continue; if (!Object.prototype.hasOwnProperty.call(obj, i)) continue; target[i] = obj[i]; } return target; }
var x = { a: 1, b: 2, c: 3, z: 26 };
var b = x.b;
var y = _objectWithoutProperties(x, ["b"]);
答案 1 :(得分:102)
var clone = Object.assign({}, {a: 1, b: 2, c: 3});
delete clone.b;
或者如果您接受未定义的属性:
var clone = Object.assign({}, {a: 1, b: 2, c: 3}, {b: undefined});
答案 2 :(得分:53)
要添加到Ilya Palkin的答案:您甚至可以动态删除密钥:
const x = {a: 1, b: 2, c: 3, z:26};
const objectWithoutKey = (object, key) => {
const {[key]: deletedKey, ...otherKeys} = object;
return otherKeys;
}
console.log(objectWithoutKey(x, 'b')); // {a: 1, c: 3, z:26}
console.log(x); // {a: 1, b: 2, c: 3, z:26};
来源:
答案 3 :(得分:50)
对于无法使用ES6的用户,可以使用<iframe allowfullscreen="" frameborder="0" height="360" src="https://www.youtube.com/embed/Some_Video" width="640"></iframe>
或lodash
。
underscore
或_.omit(x, 'b')
。
ramda
答案 4 :(得分:18)
您可以为它编写一个简单的辅助函数。 Lodash具有相同的功能,名称相同:omit
function omit(obj, omitKey) {
return Object.keys(obj).reduce((result, key) => {
if(key !== omitKey) {
result[key] = obj[key];
}
return result;
}, {});
}
omit({a: 1, b: 2, c: 3}, 'c') // {a: 1, b: 2}
另请注意,它比Object.assign快,然后删除:http://jsperf.com/omit-key
答案 5 :(得分:12)
我使用这种单线ES6语法
BAD.DATA
答案 6 :(得分:9)
也许是这样的:
var copy = Object.assign({}, {a: 1, b: 2, c: 3})
delete copy.c;
这够好吗?或者c
实际上是否会被复制?
答案 7 :(得分:7)
如何?
class UserStatisticSerializer(serializers.Serializer):
user = serializers.SerializerMethodField() # not sure on these fields
max_date = serializers.SerializerMethodField() # not sure on these fields
min_date = serializers.SerializerMethodField() # not sure on these fields
statistics = StatisticSerializer(many=True) # <---
class Meta:
model = User
fields = [
'id', 'first_name', 'last_name', 'email', 'gender', 'ip_address',
'statistics' # <---
]
答案 8 :(得分:6)
当你试图复制一个对象然后删除一个属性时,嘿,好像你会参与引用问题。在某些地方你必须分配原始变量,以便javascript创建一个新值。
我使用的简单技巧(可能是可怕的)是
var obj = {"key1":"value1","key2":"value2","key3":"value3"};
// assign it as a new variable for javascript to cache
var copy = JSON.stringify(obj);
// reconstitute as an object
copy = JSON.parse(copy);
// now you can safely run delete on the copy with completely new values
delete copy.key2
console.log(obj)
// output: {key1: "value1", key2: "value2", key3: "value3"}
console.log(copy)
// output: {key1: "value1", key3: "value3"}
答案 9 :(得分:6)
以下是我认为尚未提及的忽略动态键的选项:
const obj = { 1: 1, 2: 2, 3: 3, 4: 4 };
const removeMe = 1;
const { [removeMe]: removedKey, ...newObj } = obj;
removeMe
的别名为removedKey
,并被忽略。 newObj
成为{ 2: 2, 3: 3, 4: 4 }
。请注意,删除的键不存在,其值不只是设置为undefined
。
答案 10 :(得分:4)
Lodash omit
let source = //{a: 1, b: 2, c: 3, ..., z:26}
let copySansProperty = _.omit(source, 'b');
// {a: 1, c: 3, ..., z:26}
答案 11 :(得分:3)
我最近以非常简单的方式做到了:
const obj = {a: 1, b: 2, ..., z:26};
仅使用 spread运算符即可分隔不需要的属性:
const {b, ...rest} = obj;
...和 object.assign 仅包含“其余”部分:
const newObj = Object.assign({}, {...rest});
答案 12 :(得分:3)
使用对象分解
const omit = (prop, { [prop]: _, ...rest }) => rest;
const obj = { a: 1, b: 2, c: 3 };
const objWithoutA = omit('a', obj);
console.log(objWithoutA); // {b: 2, c: 3}
答案 13 :(得分:2)
您还可以使用传播运算符来执行此操作
select * from pg_namespace where nspowner in (select usesysid from pg_user where usename in ('one', 'two'));
答案 14 :(得分:2)
那呢? 我从来没有发现这种模式,但是我只是试图排除一个或多个属性,而无需创建额外的对象。这似乎可以完成工作,但是有一些副作用我看不到。当然不是很可读。
const postData = {
token: 'secret-token',
publicKey: 'public is safe',
somethingElse: true,
};
const a = {
...(({token, ...rest} = postData) => (rest))(),
}
/**
a: {
publicKey: 'public is safe',
somethingElse: true,
}
*/
答案 15 :(得分:2)
如果你正在处理一个巨大的变量,你不想复制它然后删除它,因为这样效率很低。
带有hasOwnProperty检查的简单for循环应该有效,并且它更适合未来的需求:
for(var key in someObject) {
if(someObject.hasOwnProperty(key) && key != 'undesiredkey') {
copyOfObject[key] = someObject[key];
}
}
答案 16 :(得分:2)
我不知道你到底想用它做什么,所以我不确定这是否适合你,但我只是做了以下工作并且它适用于我的用例:
run()
答案 17 :(得分:1)
如果您使用 Ramda,您可以使用其 omit 和 clone 函数对您的对象进行深度克隆并省略不必要的字段。
var object = {a: 1, b: 2, c: 3, y:25, z:26};
R.clone(R.omit(["z", "y"], object));
答案 18 :(得分:1)
我以这种方式完成了它,例如我的Redux reducer中的例子:
const clone = { ...state };
delete clone[action.id];
return clone;
换句话说:
const clone = { ...originalObject } // note: original object is not altered
delete clone[unwantedKey] // or use clone.unwantedKey or any other applicable syntax
return clone // the original object without the unwanted key
答案 19 :(得分:1)
const x = {obj1: 1, pass: 2, obj2: 3, obj3:26};
const objectWithoutKey = (object, key) => {
const {[key]: deletedKey, ...otherKeys} = object;
return otherKeys;
}
console.log(objectWithoutKey(x, 'pass'));
答案 20 :(得分:1)
上面使用结构化的解决方案的确存在一个事实,那就是您拥有一个已使用的变量,如果使用该变量,可能会引起ESLint的抱怨。
这是我的解决方案:
const src = { a: 1, b: 2 }
const result = Object.keys(src)
.reduce((acc, k) => k === 'b' ? acc : { ...acc, [k]: src[k] }, {})
在大多数平台上(除非使用Babel,否则IE除外),您也可以这样做:
const src = { a: 1, b: 2 }
const result = Object.fromEntries(
Object.entries(src).filter(k => k !== 'b'))
答案 21 :(得分:0)
我有一个object
,我想在使用其方法后将其删除。这就是对我有用的。
/* Sample data */
let items = [
{
name: 'John',
doc: {
set: async (item) => {/*...sets docs on remote server*/}
}
},{
name: 'Mary',
doc: {
set: async (item) => {/*...sets docs on remote server*/}
}
},{
name: 'Jack',
doc: {
set: async (item) => {/*...sets docs on remote server*/}
}
}
]
/* mapping to promises */
const promises = items.map(({doc, ...item}) => doc.set(item));
// utilized doc and utilized `rest` of the items :)
祝你好运:)
答案 22 :(得分:0)
这是我在打字稿上的两美分,略微来自@Paul的回答,而使用 reduce 。
function objectWithoutKey(object: object, keys: string[]) {
return keys.reduce((previousValue, currentValue) => {
// @ts-ignore
const {[currentValue]: undefined, ...clean} = previousValue;
return clean
}, object)
}
// usage
console.log(objectWithoutKey({a: 1, b: 2, c: 3}, ['a', 'b']))
答案 23 :(得分:0)
我有一个名为: options 并带有一些键的对象
let options = {
userDn: 'somePropertyValue',
username: 'someValue',
userSearchBase: 'someValue',
usernameAttribute: 'uid',
userPassword: 'someValue'
}
我想记录所有对象的excelp userPassword属性,因为我正在测试某些东西,我正在使用此代码:
console.log(Object.keys(options).map(x => x + ': ' + (x === "userPassword" ? '---' : options[x])));
如果要使其动态,只需创建一个函数即可,而不是显式放置 userPassword ,您可以放置要排除的属性的值
答案 24 :(得分:0)
这也应该做到;我很确定'delete'也可以与关联数组一起使用:
var copy = (obj, del)=>{
delete obj.del;
return obj;
}
答案 25 :(得分:0)
如果您使用 typescript,delete 关键字解决方案将引发编译错误,因为它违反了您实例化的对象的约定。 ES6 扩展运算符解决方案 (import numpy as np
import pandas as pd
import string
from codetiming import Timer
np.random.seed(10)
# Construct a toy dataframe
RANDS_CHARS = np.array(list(string.ascii_letters + string.digits),
dtype=(np.str_, 1))
num_firsts = 1000
firsts = ''.join(np.random.choice(RANDS_CHARS, num_firsts))
print(f"N: {num_firsts}")
tups = []
num_third = 4
num_fourth = 3
for i, first in enumerate(firsts):
# Each "first" group has its own unique set of "third" and "fourth" index possibilities.
thirds = np.random.choice(range(i * 100, i * 100 + 50), size=num_third, replace=False)
# It's possible for the positive group's "third" index to be identical to one of the negative groups.
if np.random.uniform() < 0.1:
thirds[0] = thirds[1]
fourths = np.random.choice(range(i * 100 + 1000, i * 100 + 1050), size=num_fourth, replace=False)
for (i, third) in enumerate(thirds):
if i == 0:
second = "positive"
else:
second = "negative"
for fourth in fourths:
tups.append((first, second, third, fourth))
num_data = len(tups)
index = pd.MultiIndex.from_tuples(tups, names=["first", "second", "third", "fourth"])
x = np.random.randint(low=0, high=2, size=num_data, dtype=bool)
input_df = pd.DataFrame(index=index, data={"x": x}).reset_index()
# Complication: Not all groups when grouped by "fourth" will have the same indices. Most indices will be shared by most
# "fourth" groups, but the intersection is not complete.
mask = np.ones(num_data, dtype=bool)
mask[[17, 18]] = False
input_df = input_df[mask]
input_df = input_df.set_index(["first", "second", "third", "fourth"])
dfs = []
with Timer(text="Douple loop {:.3f} s"):
# For for each "first" group:
for first, first_df in input_df.groupby("first"):
# Separate the positive group and negative groups
positive_mask = first_df.index.get_level_values("second") == "positive"
first_df = first_df.droplevel(["first"])
positive_df = first_df[positive_mask]
negative_dfs = first_df[~positive_mask]
positive_df = positive_df.droplevel(["second", "third"])
# Do some computations w.r.t. each negative "third" group and its corresponding positive group.
for third, negative_df in negative_dfs.groupby("third"):
negative_df = negative_df.droplevel(["second", "third"])
# Compare the positive/negative group based on their "fourth" indices. Note that for indices not in their
# intersection "False" is assigned.
true_true = negative_df["x"] & positive_df["x"]
true_false = negative_df["x"] & ~positive_df["x"]
false_false = ~negative_df["x"] & ~positive_df["x"]
false_true = ~negative_df["x"] & positive_df["x"]
df = pd.DataFrame({
"true_true": true_true,
"true_false": true_false,
"false_false": false_false,
"false_true": false_true
}).reset_index()
df["first"] = first
df["second"] = "negative"
df["third"] = third
dfs.append(df)
# Output: A big dataframe of the computed values of all the negative "third" groups.
output_df = pd.concat(dfs)
output_df = output_df.set_index(["first", "second", "third", "fourth"], verify_integrity=True).sort_index()
with Timer(text="Vectorized {:.3f} s"):
# Get positive/negative entries side by side
dfi = input_df['x'].unstack(level=['second'])
# Copy positive entries into a new column according to the {"first" x "fourth"} index of each for comparison with
# negative indices.
dfi["_positive"] = input_df["x"].loc[:, "positive", :, :].droplevel("third").reindex(
dfi.index.droplevel("third")).values
# Drop the "third" groups where there was no negative entry to begin with.
dfi = dfi[~dfi["negative"].isna()]
# Do the computation.
dfi['true_true'] = dfi["negative"] & dfi["_positive"]
dfi['true_false'] = dfi["negative"] & ~dfi["_positive"]
dfi['false_false'] = ~dfi["negative"] & ~dfi["_positive"]
dfi['false_true'] = ~dfi["negative"] & dfi["_positive"]
# Reformat to match output_df indices for comparison
dfi = dfi.drop(columns=["positive", "negative", "_positive"])
dfi["second"] = "negative"
dfi = dfi.set_index("second", append=True).reorder_levels(["first", "second", "third", "fourth"])
# Filter out the empty rows from the correct, slow method to check correctness of the rows we did calculate.
compare_rows = output_df.any(axis=1)
assert output_df[compare_rows].equals(dfi)
) 可能会根据您在项目中使用的 linting 配置引发错误,因为未使用 const {x, ...keys} = object
变量。所以我想出了这个解决方案:
x
它使用Object.entries方法(获取原始对象的键/值对数组)和数组方法filter和reduce的组合来解决问题。它看起来很冗长,但我认为有一个单行可链接的解决方案很好。
答案 26 :(得分:0)
使用 lodash 干净快速,使用此解决方案,您可以删除多个键,并且无需更改原始对象。这在不同情况下更具可扩展性和可用性:
import * as _ from 'lodash';
function cloneAndRemove(
removeTheseKeys: string[],
cloneObject: any,
): object | never {
const temp = _.cloneDeep(cloneObject);
removeTheseKeys.forEach((key) => {
delete temp[key];
});
return temp;
}
export { cloneAndRemove };
答案 27 :(得分:-1)
使用 loadash deepclone 功能你可以:
const _obj = _.cloneDeep(obj);
delete _obj.key;
首先将整个对象克隆到新对象中,然后从克隆对象中删除所需的键,以免影响原始对象。