← Назад к вопросам
Развертывание вложенного объекта в плоскую структуру
2.0 Middle🔥 191 комментариев
#JavaScript Core#Архитектура и паттерны
Условие
Напишите функцию flattenObject(obj), которая преобразует вложенный объект в плоскую структуру с точечной нотацией ключей.
Требования
- Функция должна рекурсивно обходить все вложенные объекты
- Ключи в результате должны быть соединены через точку
- Массивы обрабатывать с числовыми индексами в ключах
Примеры
flattenObject({
a: {
b: 1,
c: {
d: 2
}
},
e: 3
});
// Результат: { "a.b": 1, "a.c.d": 2, "e": 3 }
flattenObject({
user: {
name: "John",
address: {
city: "Moscow"
}
}
});
// Результат: { "user.name": "John", "user.address.city": "Moscow" }
Бонус
Реализуйте обратную функцию unflattenObject, которая восстанавливает вложенную структуру.
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Решение: Развертывание вложенного объекта в плоскую структуру
Задача и её применение
Развёртывание вложенных объектов часто требуется при работе с конфигурациями, сохранением в базы данных, экспортом в CSV и прочих сценариях, где нужна плоская структура данных. Эта функция использует рекурсию для обхода всех уровней вложенности.
Базовое решение
function flattenObject(obj, prefix = '') {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
const newKey = prefix ? `${prefix}.${key}` : key;
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
Object.assign(result, flattenObject(value, newKey));
} else {
result[newKey] = value;
}
}
}
return result;
}
Версия с поддержкой массивов
function flattenObject(obj, prefix = '') {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
const newKey = prefix ? `${prefix}.${key}` : key;
if (Array.isArray(value)) {
value.forEach((item, index) => {
const arrayKey = `${newKey}[${index}]`;
if (item !== null && typeof item === 'object' && !Array.isArray(item)) {
Object.assign(result, flattenObject(item, arrayKey));
} else {
result[arrayKey] = item;
}
});
} else if (value !== null && typeof value === 'object') {
Object.assign(result, flattenObject(value, newKey));
} else {
result[newKey] = value;
}
}
}
return result;
}
TypeScript версия
type FlatObject = Record<string, any>;
function flattenObject(
obj: Record<string, any>,
prefix: string = ''
): FlatObject {
const result: FlatObject = {};
Object.entries(obj).forEach(([key, value]) => {
const newKey = prefix ? `${prefix}.${key}` : key;
if (
value !== null &&
typeof value === 'object' &&
!Array.isArray(value)
) {
Object.assign(result, flattenObject(value, newKey));
} else {
result[newKey] = value;
}
});
return result;
}
Обратная функция - unflattenObject
function unflattenObject(obj) {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
const keys = key.split('.');
let current = result;
for (let i = 0; i < keys.length - 1; i++) {
const k = keys[i];
if (!(k in current)) {
current[k] = {};
}
current = current[k];
}
current[keys[keys.length - 1]] = value;
}
}
return result;
}
Примеры использования
const nested = {
a: {
b: 1,
c: {
d: 2
}
},
e: 3
};
const flattened = flattenObject(nested);
console.log(flattened);
// { "a.b": 1, "a.c.d": 2, "e": 3 }
const user = {
user: {
name: "John",
address: {
city: "Moscow",
zip: "101000"
}
}
};
const flat = flattenObject(user);
console.log(flat);
// Результат с развёрнутыми ключами
const flattedData = { "a.b": 1, "a.c.d": 2, "e": 3 };
const unflattened = unflattenObject(flattedData);
console.log(unflattened);
// Восстановленная структура
Версия с параметрами сепаратора
function flattenObject(obj, prefix = '', separator = '.') {
const result = {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) {
const value = obj[key];
const newKey = prefix ? `${prefix}${separator}${key}` : key;
if (value !== null && typeof value === 'object' && !Array.isArray(value)) {
Object.assign(result, flattenObject(value, newKey, separator));
} else {
result[newKey] = value;
}
}
}
return result;
}
Реальные применения
- MongoDB: сохранение вложенных данных в плоском формате
- CSV экспорт: преобразование объектов в табличный формат
- Конфигурации: хранение вложенных параметров с точечной нотацией
- Кэширование: индексирование вложенных значений
Ключевые моменты
- Рекурсия: глубокий обход всех уровней
- hasOwnProperty: исключает наследованные свойства
- Null check: null является объектом в JavaScript
- Array check: массивы должны обрабатываться отдельно
- Object.assign: объединяет результаты рекурсивных вызовов