【问题标题】:Create Nested Object which contains N' nested objectsfrom .txt file Javascript从 .text 文件 Javascript 创建包含 N' 个嵌套对象的嵌套对象
【发布时间】:2016-09-18 23:53:34
【问题描述】:

经过多次尝试和搜索,我决定问,因为我卡住了。我有一个这样的 txt 文件:


CITYS
CITYS.AREAS
CITYS.AREAS.STREETS
CITYS.AREAS.STREETS.HOUSES
CITYS.AREAS.STREETS.HOUSES.ROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.KITCHEN
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TV
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.VASE
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.ASTREY
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.SHAMPOO
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.CONTITIONER
CITYS.AREAS.STREETS.HOUSES.GARDEN
CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL
CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL.WATER
CITYS.AREAS.STREETS.HOUSES.GARDEN.TREE.....
CITYS.AREAS.STREETS.CARS
CITYS.AREAS.STREETS.CARS.BRAND...
CITYS.AREAS.STREETS.CARS.BRAND.LOGO.....
CITYS.AREAS.STREETS.CARS.COLOR..
CITYS.AREAS.STREETS.CARS.TYPE..


我想把它转换成这样的嵌套对象
    CITYS:{
    AREAS:{
        STREETS:{
          HOUSES:{
           ROOMS: {        
                LIVINGROOMS: {TV,TABLE:{VASE,ASTREY}},
                BATHROOMS:  {BATHTUBE:{SHAMPOO,CONTITIONER},MIRROR},                    
                ...
            },              
            GARDEN:{
                    ......              
            },
          },             
         CARS:{              
            BRAND:{LOGO},
            COLOR:{},
            TYPE:{},                
            ......
            },              
        },
    }   
}


我想做这样的事情(在阵列中)
for(var line = 0; line < lines.length; line++){

    var n = lines[line];
    var ninpieces = n.split(".");
    var name=ninpieces[ninpieces.length-1];
    var nametostore=ninpieces[ninpieces.length-2]   ;

      CreateObject(name,nametostore);
};

CreateObject=function(name,nametostore){

this.a= name;
this.b= nametostore;

newpar=this['b'];
newchild=this['a'];
this[newchild]=new Array();


if (typeof this[newpar] != "object") {
this[newpar]=new Array();
}

this[newchild].push(name);
this[newpar].push(this[newchild])
stractureobj.push(this[newpar])
} 

是我在 stackoverflow 中找到的东西的组合,但它不起作用。

【问题讨论】:

  • 显示您是如何在代码中获取和解析 txt 文件
  • {VASE,ASTREY} 不是有效的对象表示法。它应该类似于{VASE: 1,ASTREY: 1}
  • @trincot {VASE,ASTREY} 使用解构有效
  • stractureobj 定义在哪里?
  • @guest271314,确实如此,但我想说的是,在问题中使用它的方式,它是无效的,因为它与解构无关。

标签: javascript object multidimensional-array


【解决方案1】:

您可以使用以下代码。这个“算法”还通过它们的全点名称临时存储属性,作为相应嵌套对象的同义词。这样,它可以快速检索下一行对象的注入位置。

请注意,如果输入已排序,则该算法的执行速度最快。如有必要,您可以使用lines.sort() 进行此操作。

function addNestedObject(obj, lines) {
    var map = { '': obj }; // Set starting point for empty path
    function addLine(line) {
        var name = line.split(".").pop();
        var path = line.substr(0, line.length-name.length-1);
        if (!map[path]) addLine(path); // recurse to create parent
        if (!map[line]) map[line] = map[path][name] = {}; // set name & line synonym
    }
    // Process each line with above private function.
    for (var line of lines.slice().sort()) addLine(line);
    return obj; // Might be useful to have as return value as well 
};

// Sample input
var lines = [
    'CITYS.AREAS',
    'CITYS.AREAS.STREETS',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TV',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.VASE',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.ASTREY',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.SHAMPOO',
    'CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.CONTITIONER',
    'CITYS.AREAS.STREETS.HOUSES.GARDEN',
    'CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL',
    'CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL.WATER',
    'CITYS',
];

var stractureobj = { 'otherProperty': 42 };

// Convert lines to nested object and add to stractureobj
addNestedObject(stractureobj, lines);

// Output in snippet
document.querySelector('pre').textContent=JSON.stringify(stractureobj, null, 4);
&lt;pre&gt;&lt;/pre&gt;

上面使用了一个对象stractureobj,它已经有自己的属性,必须添加嵌套结构。

如果您只想拥有一个只有嵌套结构的对象,而没有别的,您可以使用空对象调用它并分配返回值:

var stractureobj = addNestedObject({}, lines);

归结为与此相同:

var stractureobj = {};
addNestedObject(stractureobj, lines);

【讨论】:

  • 非常感谢我的朋友的帮助。你的答案是我所要求的,但是当我在我的真实文档上使用它时它不起作用,因为我不知道我有类似的东西: CITYS.AREAS.STREETS.HOUSES.ROOMS.KITCHEN CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TV 再次感谢您的帮助
  • 我明白了。尽管您已经接受了答案,但我仍然更新了我的答案以创建由于此类“缺失”行而缺失的对象。
  • 我在完成我的评论之前不小心按了 Enter 并且听起来很粗鲁.. sry :) 我相信如果我知道我有一些像我上面所说的元素并将它们包含在我的答案中,你的代码将是完美的。 guest271314 答案适用于我的文件。我还想问你:我的下一步是将 txt 文件转换为 html,如下所示:
    等等。我首先将其转换为 obj 并尝试将其导出为 html 的方法是好的还是有更好的方法。
  • 请注意,我的答案自您第一次发表评论以来已更新,因此它现在也适用于您在第一次发表评论的情况。至于您的后续问题:是的,创建对象结构当然是获得该 HTML 的好方法。
  • 是的,它完美无缺。非常感谢您,我可以使用它:) 也感谢有用的 cmets
【解决方案2】:

您可以使用String.prototype.split()RegExp /\n/ 作为参数在换行符处分割文本文件,Array.prototype.filter() 和参数Boolean 用于从数组中删除空项;将stractureobj 设置为空对象;使用单个for 循环,Array.prototype.reduce() 设置stractureobj 的属性

for (var line = 0
     , stractureobj = {}
     , lines = textFileContents.split(/\n/).filter(Boolean)
     ; line < lines.length
     ; line++) {
  var n = lines[line];
  if (line === 0) {
    stractureobj[lines[line]] = {}
  } else {
    var ninpieces = n.split(/\./).filter(Boolean);
    ninpieces.reduce(function(obj, prop, index) {
      var curr = ninpieces[index + 1];
      if (!obj[prop] && !!curr) {
        obj[prop] = {
          [curr]: {}
        };
      } else {
        if (obj[prop] && curr 
          && !obj[prop][curr]) {
            obj[prop][curr] = {}
        }
      }
      return obj[prop]
    }, stractureobj)
  }
};

for (var line = 0
     , stractureobj = {}
     , lines = document.querySelector("pre")
               .textContent.split(/\n/).filter(Boolean)
     ; line < lines.length
     ; line++) {
  var n = lines[line];
  if (line === 0) {
    stractureobj[lines[line]] = {}
  } else {
    var ninpieces = n.split(/\./).filter(Boolean);
    ninpieces.reduce(function(obj, prop, index) {
      var curr = ninpieces[index + 1];
      if (!obj[prop] && !!curr) {
        obj[prop] = {
          [curr]: {}
        };
      } else {
        if (obj[prop] && curr && !obj[prop][curr]) {
          obj[prop][curr] = {}
        }
      }
      return obj[prop]
    }, stractureobj)
  }
};

document.querySelectorAll("pre")[1].textContent = JSON.stringify(stractureobj, null, 2)
pre:nth-of-type(1) {
  display: none;
}
<pre>CITYS
CITYS.AREAS
CITYS.AREAS.STREETS
CITYS.AREAS.STREETS.HOUSES
CITYS.AREAS.STREETS.HOUSES.ROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.KITCHEN
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TV
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.VASE
CITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.ASTREY
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.SHAMPOO
CITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.CONTITIONER
CITYS.AREAS.STREETS.HOUSES.GARDEN
CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL
CITYS.AREAS.STREETS.HOUSES.GARDEN.POOL.WATER
CITYS.AREAS.STREETS.HOUSES.GARDEN.TREE
CITYS.AREAS.STREETS.CARS
CITYS.AREAS.STREETS.CARS.BRAND
CITYS.AREAS.STREETS.CARS.BRAND.LOGO
CITYS.AREAS.STREETS.CARS.COLOR
CITYS.AREAS.STREETS.CARS.TYPE
</pre>
<pre></pre>

【讨论】:

  • 非常感谢您的帮助这个答案解决了我的问题:) !!!我的下一步是在 HTML DOM 中导出这个对象,比如 document.createElement("DIV");对于每个嵌套的 obj,但我必须以某种方式声明我想要什么类型的元素。我会尝试,如果我做不到,我会提出另一个问题。再次感谢你:)
【解决方案3】:

我猜想在 JS 中“动态”访问嵌套值以获取或设置它们是必不可少的。我认为这是一个缺失的功能。所以我决定开发两个可重用的 Object 方法。它们是Object.prototype.getNestedValue()Object.prototype.setNestedValue() 对于这些用例来说,它们是非常方便的工具,只是将您的工作变成了一项非常简单的任务。好的,让我们来看看它们是什么。

setNestedValue() 接受多个参数。如果是 "string" 类型,则除最后一个以外的所有参数都用作对象属性;如果是 "number" 类型,则将其用作数组索引。最后一个参数是最后一行的最后一个对象属性或数组索引的值。相应地。

var o = {};
o.setNestedValue("a",3,"b","value");

var o = {};
o.setNestedValue(...["a",3,"b"],"value");

是典型的用例。让我们看一个简单的例子。

Object.prototype.setNestedValue = function(...a) {
  a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                       : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                          this[a[0]].setNestedValue(...a.slice(1)))
               : this[a[0]] = a[1];
  return this;
};

var o = {};
o.setNestedValue("a",3,"x","value");
o.setNestedValue("a",2,"y","value");
o.setNestedValue("a",1,"z","value");
o.setNestedValue("a",0,"w","value");
console.log(JSON.stringify(o,null,2));

好的,现在是你解决问题的时候了;

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};

Object.prototype.setNestedValue = function(...a) {
  a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                       : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                          this[a[0]].setNestedValue(...a.slice(1)))
               : this[a[0]] = a[1];
  return this;
};

var data = "CITYS\nCITYS.AREAS\nCITYS.AREAS.STREETS\nCITYS.AREAS.STREETS.HOUSES\nCITYS.AREAS.STREETS.HOUSES.ROOMS\nCITYS.AREAS.STREETS.HOUSES.ROOMS.KITCHEN\nCITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS\nCITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TV\nCITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE\nCITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.VASE\nCITYS.AREAS.STREETS.HOUSES.ROOMS.LIVINGROOMS.TABLE.ASTREY\nCITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS\nCITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE\nCITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.SHAMPOO\nCITYS.AREAS.STREETS.HOUSES.ROOMS.BATHROOMS.BATHTUBE.CONTITIONER\nCITYS.AREAS.STREETS.HOUSES.GARDEN\nCITYS.AREAS.STREETS.HOUSES.GARDEN.POOL\nCITYS.AREAS.STREETS.HOUSES.GARDEN.POOL.WATER\nCITYS.AREAS.STREETS.HOUSES.GARDEN.TREE\nCITYS.AREAS.STREETS.CARS\nCITYS.AREAS.STREETS.CARS.BRAND\nCITYS.AREAS.STREETS.CARS.BRAND.LOGO\nCITYS.AREAS.STREETS.CARS.COLOR\nCITYS.AREAS.STREETS.CARS.TYPE",
  datarr = data.split("\n").map(e => e.split(".")), // get your list in an array
       o = {};
       datarr.forEach(a =>  o.setNestedValue(...a,""));
       console.log(JSON.stringify(o,null,2));

好吧..就是这样...就是这么简单。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多