получить конкретные ключи со значением объекта в новом объекте [дубликат]

Одна разница между реализацией Runnable и продолжением Thread заключается в том, что путем расширения Thread каждый из ваших потоков имеет уникальный объект, связанный с ним, тогда как при реализации Runnable многие потоки могут совместно использовать один и тот же экземпляр объекта.

A класс, который реализует Runnable, не является потоком и просто классом. Чтобы Runnable выполнялся потоком, вам нужно создать экземпляр Thread и передать экземпляр Runnable в качестве цели.

В большинстве случаев интерфейс Runnable должен использоваться, если вы планируете только планировать для переопределения метода run () и других методов Thread. Это важно, потому что классы не должны подклассифицироваться, если программист не намерен модифицировать или улучшать фундаментальное поведение класса.

Когда необходимо расширить суперкласс, реализация интерфейса Runnable более подходит, чем использование класс Thread. Потому что мы можем расширить другой класс, внедряя интерфейс Runnable для создания потока. Но если мы просто расширим класс Thread, мы не сможем наследовать ни от какого другого класса.

119
задан Michał Perłakowski 25 August 2016 в 16:58
поделиться

7 ответов

Вот что-то более тонкое, хотя оно не позволяет повторить список полей. Он использует «деструктурирование параметров», чтобы избежать необходимости в параметре v.

({id, title}) => ({id, title})

@ Решение EthanBrown является более общим. Вот более идиоматическая версия, которая использует Object.assign и вычисленные свойства (часть [p]):

function pick(o, ...props) {
    return Object.assign({}, ...props.map(prop => ({[prop]: o[prop]})));
}

Если мы хотим сохранить атрибуты свойств, такие как configurable и геттеры и сеттеры, а также опуская неперечислимые свойства, тогда:

function pick(o, ...props) {
    var has = p => o.propertyIsEnumerable(p),
        get = p => Object.getOwnPropertyDescriptor(o, p);

    return Object.defineProperties({},
        Object.assign({}, ...props
            .filter(prop => has(prop))
            .map(prop => ({prop: get(props)})))
    );
}
89
ответ дан user 19 August 2018 в 12:19
поделиться
  • 1
    +1 приятный ответ, торазабуро; спасибо за то, что я понял Object.assign; es6 похож на рождественскую елку с таким количеством подарков под ней. Я все еще нахожу подарки через несколько месяцев после отпуска – Ethan Brown 27 May 2015 в 20:57
  • 2
    Получена ошибка: Описание свойства должно быть объектом: undefined. Разве это не должно быть filter(...).map(prop => ({[prop]: get(prop)})))? – Endless 22 November 2017 в 04:20
  • 3
    Для вашей первой реализации pick() вы также можете сделать что-то вроде return props.reduce((r, prop) => (r[prop] = o[prop], r), {}) – Patrick Roberts 31 January 2018 в 20:47
  • 4
    к сожалению, эта версия выбора не будет безопасна по типу в потоке или машинописном тексте. если вы хотите, чтобы тип безопасности, нет пути вокруг назначения структуры оригинального объекта, а затем присваивания каждого в новый объект. – duhseekoh 8 March 2018 в 00:08

Я имею сходство с решением Итана Брауна, но еще короче - pick. Другая функция pick2 немного длиннее (и медленнее), но позволяет переименовывать свойства в соответствии с образом ES6.

const pick = (o, ...props) => props.reduce((r, p) => p in o ? {...r, [p]: o[p]} : r, {})

const pick2 = (o, ...props) => props.reduce((r, expr) => {
  const [p, np] = expr.split(":").map( e => e.trim() )
  return p in o ? {...r, [np || p]: o[p]} : r
}, {}) 

Вот пример использования:

const d = { a: "1", c: "2" }

console.log(pick(d, "a", "b", "c"))        // -> { a: "1", c: "2" }
console.log(pick2(d, "a: x", "b: y", "c")) // -> { x: "1", c: "2" }
1
ответ дан Alexandr Priezzhev 19 August 2018 в 12:19
поделиться
  • 1
    В чем причина понижения? Разве это не работает для вас? – Alexandr Priezzhev 15 June 2017 в 15:35

Мне потребовалось это разрешение, но я не знал, доступны ли предлагаемые ключи. Итак, я принял @torazaburo ответ и улучшил для моего варианта использования:

function pick(o, ...props) {
  return Object.assign({}, ...props.map(prop => {
    if (o[prop]) return {[prop]: o[prop]};
  }));
}

// Example:
var person = { name: 'John', age: 29 };
var myObj = pick(person, 'name', 'sex'); // { name: 'John' }
0
ответ дан Alwin Kesler 19 August 2018 в 12:19
поделиться

Предложение свойств остаточного / расширенного объекта объекта TC39 сделает это довольно гладким:

let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
z; // { a: 3, b: 4 }

(У него есть недостаток в создании переменных x и y которые вам могут не понадобиться.)

6
ответ дан alxndr 19 August 2018 в 12:19
поделиться

Трюк для решения этого вопроса как однострочного заключается в переводе принятого подхода: вместо того, чтобы начинать с исходного объекта orig, можно начинать с ключей, которые они хотят извлечь.

Используя Array#reduce можно сохранить каждый необходимый ключ на пустом объекте, который передается как initialValue для указанной функции.

Так же:

const orig = {
  id: 123456789,
  name: 'test',
  description: '…',
  url: 'https://…',
};

const filtered = ['id', 'name'].reduce((result, key) => { result[key] = orig[key]; return result; }, {});

console.log(filtered); // Object {id: 123456789, name: "test"}

13
ответ дан Bramus 19 August 2018 в 12:19
поделиться

Я не думаю, что есть способ сделать его намного более компактным, чем ваш ответ (или torazburo's), но в основном то, что вы пытаетесь сделать, это эмулировать операцию Underscore pick . Было бы достаточно легко повторить реализацию в ES6:

function pick(o, ...fields) {
    return fields.reduce((a, x) => {
        if(o.hasOwnProperty(x)) a[x] = o[x];
        return a;
    }, {});
}

. Тогда у вас есть удобная функция повторного использования:

var stuff = { name: 'Thing', color: 'blue', age: 17 };
var picked = pick(stuff, 'name', 'age');
36
ответ дан Ethan Brown 19 August 2018 в 12:19
поделиться
  • 1
    Благодарю. Это не ответ на мой вопрос, но очень приятное дополнение. – kirilloid 18 September 2014 в 12:48
  • 2
    (пожал плечами) Я чувствую, что есть ответ для вашего решения; нет более тонкого решения general (решение torazaburo удаляется из дополнительного глагола, но основная проблема - все имена свойств должны быть записаны дважды - означает, что он не масштабируется лучше вашего решения) , Мое решение, по крайней мере, хорошо масштабируется ... справа от функции pick один раз, и вы можете выбрать столько свойств, которые хотите, и они не будут удваивать их. – Ethan Brown 18 September 2014 в 16:58
  • 3
    Почему вы используете hasOwnProperty? Если поля выбраны вручную, даже in представляется более подходящим; хотя я бы полностью отказался от проверки и просто дал им по умолчанию undefined. – Bergi 24 November 2015 в 01:19
  • 4
    Берги, это разумный момент ... Я просто рассматриваю свойства (а не методы) в цепочке прототипов, чтобы быть странным и «вонючим». (так как они представляют собой запах кода), и я предпочитаю их фильтровать по умолчанию. Если есть приложение, которое нуждается в свойствах прототипа, хорошо ... для этого может быть вариант. – Ethan Brown 24 November 2015 в 04:34
  • 5
    как насчет массивов json! – Rizwan Patel 14 September 2017 в 12:48

Маленькое более короткое решение с использованием оператора запятой:

const pick = (O, ...K) => K.reduce((o, k) => (o[k]=O[k], o), {})
5
ответ дан shesek 19 August 2018 в 12:19
поделиться
  • 1
    как это использовать? Можете ли вы привести пример? – Tomas M 9 January 2018 в 10:52
  • 2
    Он работает так же, как другие функции pick в этом потоке: pick({ name: 'John', age: 29, height: 198 }, 'name', 'age') – shesek 11 January 2018 в 16:38
Другие вопросы по тегам:

Похожие вопросы: