доступ к массиву объектов и значениям с помощью циклов - PullRequest
0 голосов
/ 07 марта 2020

У меня проблема с обработкой доступа к значениям моего массива объектов, я пытался использовать различные формы циклов, пытался получить значения с помощью forEach, включает в себя, пытался использовать свойства объекта, но я в итоге получаю спагетти код и я можем управлять тестом, если эти значения существуют, но если они не передаются, они также передаются.

var target;

var itemValue;

function item_obj(name, type, exists) {
    this.name   = name;
    this.type   = type;
    this.exists = exists;
}

function getItemValue(itm) {

    var gm_obj = game_obj[0].item[0].name,
        i, values = [];

    console.log('getItemValue: testing:', itm);

    for (var i in gm_obj.length) {

        if(gm_obj[i].includes(itm)) {

            itm = gm_obj[i];
    console.log(itm);
        } else {

            itm = null;
        }
    }

    if (itm != null) {
        itm = new item_obj(itm, 'item', true);
        console.log('getItemValue: found:', itm);

  document.getElementById('cout').innerHTML = 'found item' + itm;

        return itm;
    } else {
        return false;
    }
}   

код должен выводить цель как объект, чтобы я мог использовать значения позже, я попробовал отдельные переменные тоже, но кажется, что l oop возвращает только первое значение.

это работает, а возвращение false - нет. он должен установить для элемента существует значение false, поэтому я могу пропустить его через аналогичную функцию, пока не найду тип и не воспользуюсь оператором switch для соответствующей обработки.

вот ручка: https://codepen.io/silconsystem/pen/oNXoBJo?editors=1111

и в этом все дело, я больше впереди в ветке разработки.

Это пинает мою задницу, кто-нибудь может дать мне несколько советов?

Приветствия Роб ..

Ответы [ 4 ]

0 голосов
/ 16 марта 2020

Используя помощь всех вас, я нашел решение и узнал немного больше. Я сделал объекты более единообразными и несу свойство типа вместо того, чтобы помещать их в именованный массив, который сделал логику поиска c одинаковой для всех типов и создал небольшую функцию, перебирающую массивы и их свойства имени, таким образом вырезая много дерьмового кода.

вот объект:

const game_objects = [          
{
    item: 
    [
        {
         name: "item",
         description: "player",
         game: "HP - 0",
         url: "../img/weapons/nothing.png",
         type: "item",
         handler: "player"
        },....
    ];

и функция:

// find the second string argument and set type
function findObject(arr, itm) {

    var found;
    console.log('findObject: searching for:',itm);

    for(let i in arr) {
        for (let j in arr[i])
            if (arr[i][j].name.includes(itm)) {

            found = arr[i][j];
        }
    }
    itm = found;
    return itm;
}

это был мой блокнот для этой проблемы

https://codepen.io/silconsystem/pen/oNXoBJo?editors=0001

объект является частью дескриптора ввода текста, используемого как: «возьми зелье» и добавляется в инвентарь игрока, если он найден, и помещается в фиксированный div, где если объекты добавляются, мы можем прокручивать колесико мыши или клавиши 1 2 3 4 для фокусировки и использовать клавиши курсора

Github: https://github.com/silconsystem/adventureJS [development / workstation-dev]

Еще раз спасибо за все время!

0 голосов
/ 07 марта 2020

Ваша структура данных не точно моделирует ваш домен. Я говорю это потому, что он не сообщает, что он моделирует.

Вы должны написать четкую спецификацию точных вопросов, на которые вы хотите, чтобы структура данных ответила, и это придаст вам форму.

Из вашего кода я получаю следующее:

По названию предмета проверьте, существует ли предмет в коллекции. Если это так, создайте новый объект с именем элемента и типом "item"

. В этом случае ваша структура данных представляет собой плоский массив имен.

Вы берете имя, затем фильтруете массив имен, чтобы увидеть, есть ли какие-либо элементы с этим именем.

Вот версия, которая работает для первого, что ваш код и данные сообщают, что вы пытаетесь сделать:

const game_obj = [
    {
        item: 
        [   
            {
                name: 
                [
                    "nothing",
                    "potion",
                    "ether",
                    "revive",
                    "helmet",       
                    "coins",    
                    "medals",
                    "crown",
                    "robes"
                ]
            },
            {
                description:
                [
                    ["none"],
                    ["small boost"],
                    ["MP boost"],
                    ["alive"],
                    ["protect head"],       
                    ["player coin"],    
                    ["luck plus"],
                    ["strenght plus"],
                    ["strenght plus"]
                ]
            },
            {
                game:
                [
                    ["none"],
                    ["HP +10"],
                    ["MP +10"],
                    ["HP +100"],
                    ["evd +3"],     
                    ["coins +10"],  
                    ["luc +5"],
                    ["str +5"],
                    ["str +1"]
                ]
            },
            {
                url:
                [
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"],
                    ["#"]
                ]
            }
        ]
    }
];
/*----------------------------------------------------------------------------------------------------------------------------*/
var target;

var itemValue;

function item_obj(name, type, exists) {
        this.name   = name;
        this.type   = type;
        this.exists = exists;
    }

function getItemValue(itm) {
    const names = game_obj[0].item[0].name

        console.log('getItemValue: testing:', itm);
    const exists = names.filter(name => name === itm)
    const result = exists.length > 0 ? exists[0] : null

        if (!result) {
      return false
    }

  const item = new item_obj(result, 'item', true);
  console.log('getItemValue: found:', item);

  document.getElementById('cout').innerHTML = 'found item' + item;

  return item;

    }   
itemValue = new item_obj(target, 'item', true);
console.log(itemValue);

var submitBtn = document.getElementById('button');
var textBox = document.getElementById('input');

submitBtn.onclick = function(event) {
  target = textBox.value;

  getItemValue(target);

  document.getElementById('cout').innerHTML = target;

}

Обратите внимание, как массив сглаживается. У вас был массив массивов с одним элементом.

Я предполагаю, однако, что вопрос, на который вы хотите, чтобы он ответил:

Учитывая название элемента, проверьте чтобы увидеть, существует ли элемент в коллекции. Если это так, создайте новый объект с именем элемента, типом «item» и свойствами этого элемента.

Эта структура данных является массивом объектов.

В качестве примера:

const ItemData = [
  {
     name: 'potion',
     description: 'strength plus',
     game: 'STR +5',
     url: '#'
  },
  {
     name: 'revive',
     description: 'small boost',
     game: 'HP +10',
     url: '#'
  }
]

Но вы должны начать с четкого описания на простом и точного языка того, что вы хотите сделать, потому что это описание псевдо -код.

Я думаю, что если вы посмотрите внимательно, вы обнаружите, что в итоге вы получаете спагетти, потому что ваше описание проблемы, которую вы собираетесь решить , это спагетти, чтобы начать с.

Вот как вы получаете элемент из этой структуры данных по имени:

const ItemData = [
  {
     name: 'potion',
     description: 'strength plus',
     game: 'STR +5',
     url: '#'
  },
  {
     name: 'revive',
     description: 'small boost',
     game: 'HP +10',
     url: '#'
  }
]

// Given a name, return the item matching that name, or null
function getItem(itemName) {
  if (!itemName) {
    return null
  }
  const matchingItem = ItemData.filter(item => item.name === itemName)
  return matchingItem.length > 0 ? matchingItem[0] : null
}

Видите, я начал с четкого изложения проблемы, которую я хочу, чтобы мой код решил. Структура данных становится очевидной, и код для работы с ней минимален и чист - потому что структура данных оптимизирована для него.

Вот рефакторинг Array.filter, который поднимает из него функцию предиката:

  const hasMatchingName = name => item => item.name === name
  const matchingItem = ItemData.filter(hasMatchingName(itemName))

В этом случае, если каждому элементу требуется type: "item" в качестве свойства, вы можете либо добавить его к данным, либо добавить его в строку, например:

// Given a name, return the item matching that name, or null
function getItem(itemName) {

  if (!itemName) {
    return null
  }
  const hasMatchingName = name => item => item.name === name

  const matchingItem = ItemData.filter(hasMatchingName(itemName))

  return matchingItem.length > 0 
    ? makeItemObject(matchingItem[0]) 
    : null
}

function makeItemObject(itemData) {
  return {...itemData, type: "item" }
}

Если вы получаете свои данные откуда-то еще, и они имеют отвратительную структуру, то у вас есть один шаг, чтобы преобразовать их в модель, необходимую для ответа на ваши вопросы, и затем вы пишете код для ответа эти вопросы, как отдельная проблема.

Но вы всегда начинаете с четкого описания результата и работаете в обратном направлении.

Еще пара моментов:

  • Не создавайте массивный блок с отступом, который в конце говорит else { return } - вместо этого выходите рано. Это уменьшает отступ, и вам не нужно читать весь код, чтобы выяснить (например, в моем коде), что если имя не передано, мы просто завершаем работу.

  • Всегда используйте const. Единственный раз, когда вам нужно использовать переменную, это когда у вас есть фактическая переменная, за которую вы должны нести ответственность. Но это очень редко. Все в этом коде является константой. Даже запрос пользователя является константой. Они запрашивают an item, и элемент, который они запрашивают, не изменяется во время выполнения кода.

0 голосов
/ 07 марта 2020

В вашем подходе есть много аспектов poli sh, но в отношении самой функции поиска:

var gm_obj = game_obj[0].item[0].name,
    i, values = [];

gm_obj - это массив массивов:

name: 
[
  ["nothing"],["potion"],["ether"],["revive"],["helmet"],
  ["coins"], ["medals"],["crown"],["robes"]
]

gm_obj. длина равна 1, поэтому for (var i in gm_obj.length) ничего не значит.

Я полагаю, что ваша предыдущая попытка была

for(var i=0; i<gm_obj.length; i++) {
    // check gm_obj[i]
}

В любом случае, вы можете перебирать имена, используя for...of

for (var obj of gm_obj) {
  // obj is [nothing], then [potion], then etc...
  // for example:
  if(["medals"].includes(itm)) {
    ...
  }
}

Это проверка на точное совпадение. Если все в порядке, вы выполняете присваивание

 itm = obj; // in your code, itm = gm_obj[i]

Превращает itm из строки в массив. Я не верю, что это твоя цель. Это должно быть

 itm = obj[0];  // still a string.

Далее в коде, если вы получили совпадение в одном l oop, а в следующем ничего нет, вы стираете найденное значение:

    } else {
        itm = null;
    }

Вы должны иметь break

   if(obj.includes(itm)) {
     itm = obj[0];
     break;
   }

или использовать временную переменную для сохранения результата. Инициализируйте его как null, так что вам не нужно else

  let result=null;
  for(obj of gm_obj) {
    if(obj.includes(itm)) {
      result = obj[0];
    }
  }

Если нормально пропустить другие элементы после совпадения, просто верните:

   if(obj.includes(itm)) {
     itm = obj[0];
     return new item_obj(itm, 'item', true);
   }

Наконец Я считаю, что это просто PO C, потому что ваш обработчик onclick не сохраняет результаты поиска.

submitBtn.onclick = function(event) {
  target = textBox.value;

  getItemValue(target); // not storing

  document.getElementById('cout').innerHTML = target;

}

Как уже говорили другие, вам нужно работать с данными, которые подходит для вашего случая использования. Если вы не можете контролировать его источник, преобразуйте его. (отображение и / или сокращение), потому что я считаю, что ваша конечная цель - получить объект, который представляет каждый атрибут элемента. Поэтому я бы работал с таким игровым объектом, как:

let  game_obj = {
  item: 
    [ 

      {name:"nothing", description:"none", game:"none", url:'#'},
      {name:"potion", description:"small boost", game:"HP +10", url:'#'},
      {name:"ether", description:"MP boost", game:"MP +10", url:'#'},
      {name:"revive", description:"alive", game:"HP +100", url:'#'},
      {name:"helmet", description:"protect head", game:"evd +3", url:'#'},
      {name:"coins", description:"player coin", game:"coins +10", url:'#'},
      {name:"medals", description:"luck plus", game:"luc +5", url:'#'},
      {name:"crown", description:"strenght plus", game:"str +5", url:'#'},
      {name:"robes", description:"strenght plus", game:"str +1", url:'#'},
    ]
  };

, а затем выполнял поиск, как

for(obj of game_obj.item) {
  if(obj.name.includes(itm) {
     // found matching obj
  }
}

Это проще понять с первого взгляда. Вот мое решение.

let  game_obj = 
  {
    item: 
    [ 
      
          {name:"nothing", description:"none", game:"none", url:'#'},
          {name:"potion", description:"small boost", game:"HP +10", url:'#'},
          {name:"ether", description:"MP boost", game:"MP +10", url:'#'},
          {name:"revive", description:"alive", game:"HP +100", url:'#'},
          {name:"helmet", description:"protect head", game:"evd +3", url:'#'},
          {name:"coins", description:"player coin", game:"coins +10", url:'#'},
          {name:"medals", description:"luck plus", game:"luc +5", url:'#'},
          {name:"crown", description:"strenght plus", game:"str +5", url:'#'},
          {name:"robes", description:"strenght plus", game:"str +1", url:'#'},
        ]
    };
/*----------------------------------------------------------------------------------------------------------------------------*/
var target;

var itemValue;
var list = document.getElementById('list'),
 cout=document.getElementById('cout'),
 submitBtn = document.getElementById('button'),
 textBox = document.getElementById('input');

function item_obj(attributes, type='', exists=false) {
		let {
     name, description,game,url 
    }=attributes;
    this.name 	= name;
  this.description 	= description;
  this.game 	= game;
  this.url 	= url;
		this.type 	= type;
		this.exists = exists;
	}

function getItemValue(itm) {

		var gm_obj = game_obj.item,
			i, values = [], foundvalue=null;
   
      list.innerHTML = '';// gm_obj.join(', ');
		  console.log('getItemValue: testing:', itm);
   
		for (var obj of gm_obj) {
      let resultMsg=`${obj.name}: nope`,
          span=document.createElement('span');
         console.log({obj});
   		if(obj.name.includes(itm)) {
        resultMsg=`found item: <b>${obj.name}</b>`;
        
        cout.innerHTML = resultMsg;
        span.className='found'
        span.innerHTML=resultMsg;
        list.appendChild(span);
        return new item_obj(obj,'item',true);
			}
      span.innerHTML=resultMsg;
      list.appendChild(span);
		}
    return false;
	}	



//itemValue = new item_obj(target, 'item', true);




submitBtn.onclick = function(event) {
  target = textBox.value;
  console.log({target});
  cout.innerHTML = `searching for: ${target}... `;
  window.setTimeout(()=>{
     itemValue=getItemValue(target);
     console.log(itemValue);
},1000);
  
  
}
@import url('https://fonts.googleapis.com/css?family=Sulphur+Point&display=swap');

body {
  margin: 20px;
  background: #888;
  font-family: 'Sulphur Point';
  
}
#list span {
flex-grow: 0;
    white-space: no-wrap;
    padding: 0 4px;
    border: 1px solid #999;
    border-radius: 3px;
    font-size: 0.8em;
    margin: 2px 5px;
    color: #000;
    background: #ccc;
}
#list span.found {
   border:2px solid #090;
   color:#080;background:#333
}
#input {
  margin: 20px 20px 20px 0;
  border:4px solid #365683;
}

#list {
      flex-wrap: wrap;
    margin-left: 20px;
    display: flex;
    border: 7px solid #654;
    border-radius: 12px;
    max-width: 200px;
    background: #000;
    width: 200px;
    height: 165px;
    padding-left: 10px;
    color: #fff;
    align-content: flex-start;
}

#button {
  border: 4px solid #567;
  border-radius: 4px;
}
#button:hover {
  border: 4px solid #000;
  color: #fff;
  background: #000;
}
#button:active {  
  border: 4px solid #000;
  color: #000;
  background: #fff;
  font-weigth: bold;
}

#out {
  display:flex;
  font-family: 'Sulphur Point';
  color: #fff;
  border: 7px solid #654;
  border-radius: 12px;
  font-weight: bold;
  font-size: 20px;
  background: #000;
  max-width: 200px;
  height: 60px;
  padding: 20px;
}
.column div,.column button,.column input {
  display:inline-flex;
}

container {
  display:flex;
  align-items:middle;
}
.column {
  
  flex-grow:0 1;
}
<container>
  <div class="column">
<input type="text" id="input"></input>
<button id="button">submit</button>
<div id="out">
  <span id="cout"></span>
</div>
  </div>
<div class="column" id="list"></div>
</container>
0 голосов
/ 07 марта 2020

Есть несколько проблем, Первый , поскольку Андреас указал, что вы используете неправильное значение l oop, для этого сценария я бы предложил использовать forEach l oop для итерации. Второй всего, что вы устанавливаете itm на null внутри l oop. Так что itm будет установлен в ноль, если он не соответствует последнему элементу. мы создали переменную found и установили true, если itm найден и возвращен false, если нет, надеюсь, это решит проблему,

(я добавил alert, чтобы вы могли видеть, был ли найден предмет или нет)

let game_obj = [
  {
    item: [
      {
        name: [
          ["nothing"],
          ["potion"],
          ["ether"],
          ["revive"],
          ["helmet"],
          ["coins"],
          ["medals"],
          ["crown"],
          ["robes"]
        ]
      },
      {
        description: [
          ["none"],
          ["small boost"],
          ["MP boost"],
          ["alive"],
          ["protect head"],
          ["player coin"],
          ["luck plus"],
          ["strenght plus"],
          ["strenght plus"]
        ]
      },
      {
        game: [
          ["none"],
          ["HP +10"],
          ["MP +10"],
          ["HP +100"],
          ["evd +3"],
          ["coins +10"],
          ["luc +5"],
          ["str +5"],
          ["str +1"]
        ]
      },
      {
        url: [["#"], ["#"], ["#"], ["#"], ["#"], ["#"], ["#"], ["#"], ["#"]]
      }
    ]
  }
];
/*----------------------------------------------------------------------------------------------------------------------------*/
var target;

var itemValue;

function item_obj(name, type, exists) {
  this.name = name;
  this.type = type;
  this.exists = exists;
}

function getItemValue(itm) {
  //   console.log(game_obj);
  var gm_obj = game_obj[0].item[0].name,
    i,
    values = [];

  //   console.log("getItemValue: testing:", itm);
  let found = false;
  gm_obj.forEach(function(gm_item) {
    if (gm_item.toString().includes(itm)) {
      itm = gm_item;
      found = true;
    }
  });

  if (!found) {
    alert("Not Found");
    return false;
  }

  if (found) {
    alert("\'"+itm + "\' includes the provided text");
    itm = new item_obj(itm, "item", true);

    // console.log("getItemValue: found:", itm);

    document.getElementById("cout").innerHTML = "found item" + itm;

    return itm;
  }
}
itemValue = new item_obj(target, "item", true);
// console.log(itemValue);

var submitBtn = document.getElementById("button");
var textBox = document.getElementById("input");

submitBtn.onclick = function(event) {
  target = textBox.value;

  getItemValue(target);

  document.getElementById("cout").innerHTML = target;
};
@import url("https://fonts.googleapis.com/css?family=Sulphur+Point&display=swap");

body {
  margin: 20px;
  background: #888;
  font-family: "Sulphur Point";
}

#input {
  margin: 20px;
  border: 4px solid #365683;
}

#list {
  position: absolute;
  left: 300px;
  top: 87px;
  border: 7px solid #654;
  border-radius: 12px;
  max-width: 200px;
  background: #000;
  width: 200px;
  height: 120px;
  color: #fff;
}

#button {
  border: 4px solid #567;
  border-radius: 4px;
}
#button:hover {
  border: 4px solid #000;
  color: #fff;
  background: #000;
}
#button:active {
  border: 4px solid #000;
  color: #000;
  background: #fff;
  font-weigth: bold;
}

#out {
  font-family: "Sulphur Point";
  color: #fff;
  border: 7px solid #654;
  border-radius: 12px;
  font-weight: bold;
  font-size: 20px;
  background: #000;
  max-width: 200px;
  height: 80px;
  padding: 20px;
}
<!DOCTYPE html>
<html lang="en">
  <head>
   
  </head>
  <body>
    <input type="text" id="input"></input>
<button id="button">submit</button>
<div id="out">
  <span id="cout"></span>
</div>
<div id="list"></div>
 
  </body>
</html>
...