最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

recursion - How to flatten a JavaScript object into a daisy chain like form? - Stack Overflow

programmeradmin3浏览0评论

I want to flatten an object like this...

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [
      { miles: 10150, code: 'REV01', changes: },
      { miles: 20021, code: 'REV02', changes: [
        { type: 'asthetic', desc: 'Left tire cap' },
        { type: 'mechanic', desc: 'Engine pressure regulator' }
      ] }
    ]
  },
  visits: [
    { date: '2015-01-01', dealer: 'DEAL-001' },
    { date: '2015-03-01', dealer: 'DEAL-002' }
  ]
};

... into a daisy chain form like the following:

{
    "firstName": "John",
    "lastName": "Green",
    "car.make": "Honda",
    "car.model": "Civic",
    "car.revisions.0.miles": 10150,
    "car.revisions.0.code": "REV01",
    "car.revisions.0.changes": ,
    "car.revisions.1.miles": 20021,
    "car.revisions.1.code": "REV02",
    "car.revisions.1.changes.0.type": "asthetic",
    "car.revisions.1.changes.0.desc": "Left tire cap",
    "car.revisions.1.changes.1.type": "mechanic",
    "car.revisions.1.changes.1.desc": "Engine pressure regulator",
    "visits.0.date": "2015-01-01",
    "visits.0.dealer": "DEAL-001",
    "visits.1.date": "2015-03-01",
    "visits.1.dealer": "DEAL-002"
}

Here's my (failed) attempt:

function flatten(obj) {
    var flattenObject = {};

    // iterate given object
    for (let x in obj) {
        if (typeof obj[x] == 'string') {
            flattenObject[x] = obj[x];
        }

        if (typeof obj[x] == 'object') {
            for (let y in obj[x]) {
                flattenObject[x + '.' + y] = obj[x][y];
            }
        }
    }

    return flattenObject;
}

I quickly started repeating code unnecessarily in order to daisy chain inner objects and arrays. This is definitely something that needs recursion. Any ideas?

EDIT: This question is similar to other questions but not a duplicate. This question requires a specific notation and nested objects and arrays at the same time.

EDIT: I've also asked the opposite, unflatten, in another question.

I want to flatten an object like this...

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [
      { miles: 10150, code: 'REV01', changes: },
      { miles: 20021, code: 'REV02', changes: [
        { type: 'asthetic', desc: 'Left tire cap' },
        { type: 'mechanic', desc: 'Engine pressure regulator' }
      ] }
    ]
  },
  visits: [
    { date: '2015-01-01', dealer: 'DEAL-001' },
    { date: '2015-03-01', dealer: 'DEAL-002' }
  ]
};

... into a daisy chain form like the following:

{
    "firstName": "John",
    "lastName": "Green",
    "car.make": "Honda",
    "car.model": "Civic",
    "car.revisions.0.miles": 10150,
    "car.revisions.0.code": "REV01",
    "car.revisions.0.changes": ,
    "car.revisions.1.miles": 20021,
    "car.revisions.1.code": "REV02",
    "car.revisions.1.changes.0.type": "asthetic",
    "car.revisions.1.changes.0.desc": "Left tire cap",
    "car.revisions.1.changes.1.type": "mechanic",
    "car.revisions.1.changes.1.desc": "Engine pressure regulator",
    "visits.0.date": "2015-01-01",
    "visits.0.dealer": "DEAL-001",
    "visits.1.date": "2015-03-01",
    "visits.1.dealer": "DEAL-002"
}

Here's my (failed) attempt:

function flatten(obj) {
    var flattenObject = {};

    // iterate given object
    for (let x in obj) {
        if (typeof obj[x] == 'string') {
            flattenObject[x] = obj[x];
        }

        if (typeof obj[x] == 'object') {
            for (let y in obj[x]) {
                flattenObject[x + '.' + y] = obj[x][y];
            }
        }
    }

    return flattenObject;
}

I quickly started repeating code unnecessarily in order to daisy chain inner objects and arrays. This is definitely something that needs recursion. Any ideas?

EDIT: This question is similar to other questions but not a duplicate. This question requires a specific notation and nested objects and arrays at the same time.

EDIT: I've also asked the opposite, unflatten, in another question.

Share Improve this question edited May 23, 2017 at 12:09 CommunityBot 11 silver badge asked Mar 8, 2017 at 21:25 nunoarrudanunoarruda 2,9445 gold badges29 silver badges53 bronze badges 4
  • Are you sure you want car.revisions.0.miles over car.revisions[0].miles? I ask because asp-net.mvc will use the second one natively (however you haven't tagged that so I'm asking first). – Erik Philips Commented Mar 8, 2017 at 21:48
  • Possible duplicate of Fastest way to flatten / un-flatten nested JSON objects – Jordan Running Commented Mar 8, 2017 at 21:49
  • @ErikPhilips car.revisions.0.miles is the result I'm looking for – nunoarruda Commented Mar 8, 2017 at 21:49
  • Possible duplicate of Convert plex JavaScript object to dot notation object – Jordan Running Commented Mar 8, 2017 at 21:50
Add a ment  | 

3 Answers 3

Reset to default 6

Here's my code (typesciprt)

export const flatten = (data: object, prefix: string = '') => {
  const result: { [key: string]: string | number | null } = {};

  Object.entries(data).forEach(([key, value]) => {
    if (typeof value === 'object') {
      Object.assign(result, flatten(value, `${prefix}${key}.`));
    } else {
      result[`${prefix}${key}`] = value;
    }
  });

  return result;
};

javascript version

export const flatten = (data, prefix = '') => {
  const result = {};

  Object.entries(data).forEach(([key, value]) => {
    if (typeof value === 'object') {
      Object.assign(result, flatten(value, `${prefix}${key}.`));
    } else {
      result[`${prefix}${key}`] = value;
    }
  });

  return result;
};

You can create recursive function like this, and its important to store previous keys in one string.

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [
      { miles: 10150, code: 'REV01', changes: 0},
      { miles: 20021, code: 'REV02', changes: [
        { type: 'asthetic', desc: 'Left tire cap' },
        { type: 'mechanic', desc: 'Engine pressure regulator' }
      ] }
    ]
  },
  visits: [
    { date: '2015-01-01', dealer: 'DEAL-001' },
    { date: '2015-03-01', dealer: 'DEAL-002' }
  ]
};

function flatten(data, c) {
  var result = {}
  for(var i in data) {
    if(typeof data[i] == 'object') Object.assign(result, flatten(data[i], c + '.' + i))
    else result[(c + '.' + i).replace(/^\./, "")] = data[i]
  }
  return result
}

console.log(JSON.stringify(flatten(obj1, ''), 0, 4))

try this:

function flatten(obj)
{
  var result = {};
  (function f(e, p) {
    switch (typeof e) {
      case "object":
        p = p ? p + "." : "";
        for (var i in e)
          f(e[i], p + i);
        break;
      default:
        result[p] = e;
        break;
    }
  })(obj);
  return result;
}

var obj1 = {
  firstName: 'John',
  lastName: 'Green',
  car: {
    make: 'Honda',
    model: 'Civic',
    revisions: [{
      miles: 10150,
      code: 'REV01',
    }, {
      miles: 20021,
      code: 'REV02',
      changes: [{
        type: 'asthetic',
        desc: 'Left tire cap'
      }, {
        type: 'mechanic',
        desc: 'Engine pressure regulator'
      }]
    }]
  },
  visits: [{
    date: '2015-01-01',
    dealer: 'DEAL-001'
  }, {
    date: '2015-03-01',
    dealer: 'DEAL-002'
  }]
};

console.log(flatten(obj1));

发布评论

评论列表(0)

  1. 暂无评论