Related
I have an array like this;
var specialOne = 3;
var array = [{value:"special"},{value:"1"},{value:"2"},{value:"specialOne"},{value:"4"},{value:"special"}];
And I need to convert it to this array;
var temp = [{value:"0"},{value:"1"},{value:"2"},{value:"3"},{value:"4"},{value:"5"}];
special's should be replaced with the appropriate value.
specialOne should be replaced with the given number.
How can i do this ?
More examples:
0,special,2,special,4,5 => 0,1,2,3,4,5
7,8,9,special => 7,8,9,10
special,special,10 => 8,9,10
Maybe this is what you are after
var specialOne = 3;
var array1 = [{value:"special"},{value:"1"},{value:"2"},{value:"specialOne"},{value:"4"},{value:"special"}];
function addspec(specialOne){
array1.forEach((o,i)=>{
if(o.value=="specialOne")o.value = specialOne.toString()
if(o.value=="special") o.value = array1[i-1]?(parseInt(array1[i-1].value)+1).toString():"0"
})
}
addspec(3)
console.log(array1)
This may help you
var specialOne = 3;
var array = [
{ value: "special" },
{ value: "1" },
{ value: "2" },
{ value: "specialOne" },
{ value: "4" },
{ value: "special" }
];
for (i = 0; i < array.length; i++) {
if (array[i].value == 'specialOne') {
array[i].value = String(specialOne);
console.log(array);
} else if (array[i].value == 'special') {
array[i].value = String(0);
array.pop()
array.push( { value: String(5) } );
}
}
for (let i = 0; i < array.length; i++) {
if (array[i].value === "special") array[i].value = i.toString();
if (array[i].value === "specialOne") array[i].value = specialOne.toString();
};
When you need to modify an array you should try to use a 'for' loop first. It is the most efficient as it will not modify the index of the array and will not return a new array (Imagine you have to 10 000 items to modify in your array... ).
Here it's very simple, you itere the array, if the condition match you modify the value (of the array itself).
Something like this?
var specialOne = 3;
var array = [{
value: "special"
}, {
value: "1"
}, {
value: "2"
}, {
value: "specialOne"
}, {
value: "4"
}, {
value: "special"
}];
function getValues(array) {
let counterSync = 0;
let backCheck = [];
let inFlow = false;
let backCheckOnce = false;
return array.map((m, i) => {
if (isNaN(parseInt(m.value))) {
if (inFlow || window[m.value]) {
m.value = "" + (window[m.value] || (counterSync + 1));
} else {
if (i === 0) {
backCheckOnce = true;
}
backCheck.push(m);
}
} else {
inFlow = true;
// do reverse check only once
if (backCheckOnce) {
backCheck.reverse().forEach((x, idx) => x.value = "" + (+m.value - 1));
backCheckOnce = false;
}
}
counterSync = +m.value;
return m;
});
}
console.log(getValues(array));
I am having trouble displaying the random object and the properties of that random object. The goal of this project is to have a list of stockItems, and when I press a button, it selects a determined number of those objects and displays them in an HTML p tag. Right now when I try to display it, it prints out as [object]. The goal is to have the properties of the selected object on different lines.
Here is the code I am working with:
function buildShopItems(count) {
var shopItems = [], i, itemIndex;
count = stockItems.length < count ? stockItems.length : count;
function getUniqueRandomItem() { //from stock
var item;
while (true) {
item = stockItems[Math.floor(Math.random() * stockItems.length)];
if (shopItems.indexOf(item) < 0) return item;
}
}
for (i = 0; i < count; i++) {
shopItems.push(getUniqueRandomItem());
}
return shopItems;
console.log(shopItems);
}
var stockItems = [
{ item: "sword", type: "weapon", weight: "5 lbs.", cost: "10 gold" },
{ item: "hammer", type: "weapon", weight: "8 lbs.", cost: "7 gold" }
//...
];
var shopItems = buildShopItems(1);
console.log(shopItems);
document.getElementById("item").innerHTML = shopItems.item;
document.getElementById("type").innerHTML = shopItems.type;
document.getElementById("weight").innerHTML = shopItems.weight;
document.getElementById("cost").innerHTML = shopItems.cost;
The problem was with your usage of indexOf. You can use indexOf to search for an object because in javascript you can't compare object using == or === and indexOf uses ===. Also made some syntax updates for you.
'use strict'
const stockItems = [
{ item: "sword", type: "weapon", weight: "5 lbs.", cost: "10 gold" },
{ item: "hammer", type: "weapon", weight: "8 lbs.", cost: "7 gold" }
];
function isEquivalent(a, b) {
// Create arrays of property names
const aProps = Object.getOwnPropertyNames(a);
const bProps = Object.getOwnPropertyNames(b);
// If number of properties is different,
// objects are not equivalent
if (aProps.length != bProps.length) {
return false;
}
for (let i = 0; i < aProps.length; i++) {
const propName = aProps[i];
// If values of same property are not equal,
// objects are not equivalent
if (a[propName] !== b[propName]) {
return false;
}
}
// If we made it this far, objects
// are considered equivalent
return true;
}
// normal indexof will not work with object because it uses strict equality
function myIndexOf(array, object) {
for (let i = 0; i < array.length; i++) {
if (isEquivalent(array[i], object)) return i;
}
return -1;
}
function getUniqueRandomItem(shopItems) { //from stock
var item;
while (true) {
item = stockItems[Math.floor(Math.random() * stockItems.length)];
if (myIndexOf(shopItems, item) < 0) return item;
}
}
function buildShopItems(count) {
count = stockItems.length < count ? stockItems.length : count;
const shopItems = [];
for (let i = 0; i < count; i++) {
const item = getUniqueRandomItem(shopItems);
shopItems.push(item);
}
return shopItems;
}
const shopItems = buildShopItems(1);
console.log(shopItems);
I have the following js array:
for(var j = 0; j < array.length; j++){
arr.push([array[j][0],array[j][1],array[j][2]]);
}
And it translates into this:
Number, type, qty
[[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]]
What I've been trying to do is to filter the unique product number array[j][0] and sum the qty array[j][2] if there's more than one and I was able to do the unique filter by doing the following:
for(var o = 0; o < arr.length; o++){
if (!n[arr[o][1]]){
n[arr[o][1]] = true
r.push(arr[o]);
}
}
I would like your help to figure this out.. What I'm expecting to achieve is something like this:
[[12345, "product", "25"],[1234567, "other", "10"]]
Since product 12345 was repeated I only need to display it once and sum the qty of the other products with the same product number.
var productIndex = {};
var result = [];
for (var i = 0; i < arr.length; i++) {
var productId = arr[i][0];
if (productIndex[productId] === undefined) {
productIndex[productId] = result.length;
result.push(arr[i]);
} else {
var index = productIndex[productId];
result[index][2] = String(+result[index][2] + +arr[i][2]);
}
}
I am sure there are better ways. But I just changed it to an object, added them and changed it back to an array. Here you go:
https://jsfiddle.net/ct6to1Lv/
var a = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var b = {};
var c = [];
for(var i = 0; i < a.length; i++) {
if(!b.hasOwnProperty(a[i][0])) {
b[a[i][0]] = {};
b[a[i][0]]['qty'] = 0;
}
b[a[i][0]]['id'] = a[i][0];
b[a[i][0]]['name'] = a[i][1];
b[a[i][0]]['qty'] += parseInt(a[i][2]);
}
for(key in b) {
c[c.length] = [b[key]['id'], b[key]['name'], b[key]['qty']];
}
$(function(){
$('#console').append(a.toString()+'<br />');
$('#console').append(JSON.stringify(b)+'<br />');
$('#console').append(c.toString());
});
var arr = [[12345, "product", "10"],[12345, "product", "15"],[1234567, "other", "10"]];
var obj = {};
arr.forEach(function(e){
var t = e[0];
if(obj[t]) {
obj[t][2] += +e[2];
} else {
t = [];
t[0] = e[0];
t[1] = e[1];
t[2] = +e[2];
obj[e[0]] = t;
}
});
var res = [];
Object.keys(obj).forEach(function(k) {
res.push(obj[k]);
});
console.log(res);
Result:
[ [ 12345, 'product', 25 ], [ 1234567, 'other', 10 ] ]
To complete the possibillities, here a solution with a temporary object, which is hidden in this.
var data = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"]],
result = function (data) {
var r = [];
data.forEach(function (a) {
if (!this[a[0]]) {
this[a[0]] = [a[0], a[1], 0];
r.push(this[a[0]]);
}
this[a[0]][2] += +a[2];
}, {});
return r;
}(data);
document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');
The reduce() method applies a function against an accumulator and each value of the array (from left-to-right) to reduce it to a single value.
See Array.prototype.reduce() and Array.prototype.sort()
var list = [[12345, "product", "10"], [12345, "product", "15"], [1234567, "other", "10"], [12345, "product", "5"]];
//first we sort the array by id
//#pv = previous value; #cv = current value
list.sort(function(pv, cv) {
var a = +pv[0],
b = +cv[0];
return a - b;
});
//reduce the array for repeated elements
//#pv = previous value; #cv = current value
var reduced = list.reduce(function (pv, cv) {
//slice keeps reference when element is an object/array
var last = pv.slice(-1)[0];
if (last === undefined) return [cv];
//compares the id
if (last[0] == cv[0])
last[2] = +last[2] + (+cv[2]); //sums values
else pv.push(cv); //order elements
return pv;
}, []); //[] initial value for #pv
console.log(reduced);
I have the following data :
[
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
]
I need to make an incremental array of arrays from it. It should look something like this :
[
[
{"name":"Blackbird","value":0,"date":1900},
{"name":"Seagull","value":1,"date":1900},
{"name":"Sparrow","value":0,"date":1900}
],
[
{"name":"Blackbird","value":0,"date":1910},
{"name":"Seagull","value":1,"date":1910},
{"name":"Sparrow","value":0,"date":1910},
{"name":"Owl","value":1,"date":1910}
],
[
{"name":"Blackbird","value":0,"date":1920},
{"name":"Seagull","value":1,"date":1920},
{"name":"Sparrow","value":0,"date":1920},
{"name":"Owl","value":1,"date":1920},
{"name":"Eagle","value":0,"date":1920},
{"name":"Albatross","value":2,"date":1920}
]
]
No matter what I have tried, I always end up with all the dates I add to the objects being equal to the last value (1920 here). I understand that the objects are copied by reference only. I have tried using array.map() (like in the answer given here, but my question was not formulated right), but I still get the same problem.
EDIT
Here's one example of code I've tried :
var temp = [];
var b = data.map(function(c, index, main) {
var year = c.date;
temp = [];
main.slice(0, index + 1).map(function(d){
var t = d.data.map(function(e){
e.date = year;
return e;
});
temp = temp.concat(t);
});
return temp;
});
console.log(b);
Here's a working example:
You need to clone the object in order to "break" the reference.
var data = [
{
"date":1900,
"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]
},
{
"date":1910,
"data":[
{"name":"Owl","value":1}
]
},
{
"date":1920,
"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]
}
];
var incremental = [];
var dataHistory = null;
for(i = 0; i < data.length; i++){
var temp = dataHistory ? dataHistory.slice() : []; //.slice to clone array
//Replace all values with current date.
for(var j = 0; j < temp.length; j++){
temp[j] = JSON.parse(JSON.stringify(temp[j])); //Clone object
temp[j].date = data[i].date;
}
//Add current date to object.
for(var j = 0; j < data[i].data.length; j++){
var aux = {
name: data[i].data[j].name,
value: data[i].data[j].value,
date: data[i].date
};
temp.push(aux);
}
dataHistory = temp;
incremental.push(temp);
}
document.body.innerHTML = '<pre>' + JSON.stringify(incremental, null, 4) + '</pre>';
If you're using jQuery you can replace:
temp[j] = JSON.parse(JSON.stringify(temp[j]));
With:
temp[j] = $.extend({}, temp[j]);
Try this one:
var data = [
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
];
var result = data.map(function(item) {
var replacement = [];
for (var key in item.data) {
var subItem = item.data[key];
subItem.date = item.date;
replacement.push(subItem);
}
return replacement;
});
document.body.innerHTML = '<pre>' + JSON.stringify(result, null, 3) + '</pre>';
Use map, iterate over the inner array, and set the date property to each object etc.
var data = [
{"date":1900,"data":[
{"name":"Blackbird","value":0},
{"name":"Seagull","value":1},
{"name":"Sparrow","value":0}
]},
{"date":1910,"data":[
{"name":"Owl","value":1}
]},
{"date":1920,"data":[
{"name":"Eagle","value":0},
{"name":"Albatross","value":2}
]}
]
data = data.map(function(obj, i, arr) {
var o = [];
arr.slice(0, i).forEach(function(item) {
item.data.forEach(function(data) {
o.push(Object.assign({}, data))
});
});
return o.concat(obj.data.map(function(item) { item.date = obj.date; return item }));
});
document.body.innerHTML = '<pre>' + JSON.stringify(data, null, 4) + '</pre>';
Object.assign with polyfill
Anyone know a good way to turn this?:
var obj = [{key1: value1,key2: value2},{key3: value3,key4: value4}];
into:
var obj = [{Key1: value1,Key2: value2},{Key3: value3,Key4: value4}];
Loop through delete and replace:
var obj = [{key1: 1,key2: 1},{key3: 1,key4: 1}];
for(var i = 0; i<obj.length;i++) {
var a = obj[i];
for (var key in a) {
if (a.hasOwnProperty(key)) {
a[key.charAt(0).toUpperCase() + key.substring(1)] = a[key];
delete a[key];
}
}
obj[i] = a;
}
As of 2019 you can use Object.fromEntries:
let populations = {london: 8.9, beijing: 21.54, mumbai: 18.41}; // March 2020
let entries = Object.entries(populations);
let capsEntries = entries.map((entry) => [entry[0][0].toUpperCase() + entry[0].slice(1), entry[1]]);
let capsPopulations = Object.fromEntries(capsEntries);
console.log(capsPopulations);
Another approach (more clean)
import * as _ from 'lodash';
function capitalizeObjectKeys(obj) {
return _.transform(obj, (result, val, key) => {
result[key.charAt(0).toUpperCase() + key.slice(1)] = val;
});
}
https://stackblitz.com/edit/js-hsqutg?embed=1&file=index.js
In my case this code worked well. Both in uppercase and lowercase with map:
to uppercase :
const newDataUpperCase = data.map( function( item ){
for(var key in item){
var upper = key.toUpperCase();
if( upper !== key ){
item[ upper ] = item;
delete item[key];
}
}
return item;
});
to lowercase :
const newDataUpperCase = data.map( function( item ){
for(var key in item){
var lower= key.toLowerCase();
if( lower!== key ){
item[ lower] = item;
delete item[key];
}
}
return item;
});
const transform = (arrObj) => {
let newObj=[];
for(let obj of arrObj) {
let temp=new Object();
let keys = Object.keys(obj);
let values = Object.values(obj);
let i=0;
keys.forEach(key => {
key=key[0].toUpperCase() + key.slice(1);
temp[`${key}`]=values[i++];
});
newObj.push(temp);
}
return newObj;
};
const arrObj = [{first: 'satya', last:'prakash'}, {college: 'AIT'}];
console.log(transform(arrObj));
If you need to capitalize just first letter you can go with Jeremiah's answer
or if you need to capitalize first letter of each word consider the following
let populations = {"london": 8.9, "beijing": 21.54, "mumbai": 18.41, "new york": 19.4};
let entries = Object.entries(populations);
// Capitalize first letter of each word
let capsEntries = entries.map((entry) => [entry[0].replace(/(^\w{1})|(\s+\w{1})/g, letter => letter.toUpperCase()), entry[1]]);
let capsPopulations = Object.fromEntries(capsEntries);
console.log(capsPopulations)
Regex adopted from this answer
Regex Explanation:
(^\w{1}): match first char of string
|: or
(\s{1}\w{1}): match one char that came after one space
g: match all
match => match.toUpperCase(): replace with can take function, so; replace match with upper case match
This will help you:
const griddata = [
{
"id_pk": 238,
"acT_ID": 238,
"desc": "Record 2",
"parent": 0,
"compdays": 5,
"logical": "1",
"quantity": "1",
"lisT_ID": 75,
"empL_ID": 1388,
"default": 8,
"level": "0",
"sortorder": 2,
"vfpRecNo": 0,
"isDeleted": false,
"clientID": 1,
"empl_num": "1388",
"duedate": "05/04/2022"
}
]
const upperCaseKeys = (data) => {
debugger;
let gridData = [];
if (data != null && data != undefined && data.length > 0) {
let keys = Object.keys(data[0]);
let upperCaseKey = [];
for (let j = 0; j < data.length; j++) {
upperCaseKey = [];
for (let i = 0; i < keys.length; i++) {
set(upperCaseKey, keys[i].toUpperCase(), data[j][keys[i]]);
}
upperCaseKey.push(...upperCaseKey);
gridData.push(Object.assign({}, upperCaseKey));
}
}
console.log("upperCaseKeys",gridData)
}
const set = (obj, prop, value) => {
obj[prop] = value;
}
upperCaseKeys(griddata)
Output:
upperCaseKeys [
{
ID_PK: 238,
ACT_ID: 238,
DESC: 'Record 2',
PARENT: 0,
COMPDAYS: 5,
LOGICAL: '1',
QUANTITY: '1',
LIST_ID: 75,
EMPL_ID: 1388,
DEFAULT: 8,
LEVEL: '0',
SORTORDER: 2,
VFPRECNO: 0,
ISDELETED: false,
CLIENTID: 1,
EMPL_NUM: '1388',
DUEDATE: '05/04/2022'
}
]
use lodash's _.capitalize function
_.capitalize('firstName') => FirstName