Get particular values inbetween an array javascript? - javascript

I have an array like,
0: "City1"
1: {name="sds", age="asd",....}
2: {name="sweds", age="accxsd",....}
3: {name="sdqws", age="asssd",....}
4: "City2"
... and many more
So I need to get the elements between index[0] and index[4],
Am able to check the string and object using typeof
for(i=0; i<=arr.length; i++){
if(typeof arr[i] == 'string'){
... // need to find next element eith type string
}
}
Is there a way to find the next element in an array whose value is string, so I can get elements between them.

You can use this alternative using the function reduce.
This approach builds an object grouping the objects into an array with the found string value.
var array = [ "City1", {name:"sds", age:"asd"}, {name:"sweds", age:"accxsd"}, {name:"sdqws", age:"asssd"}, "City2", {name:"sds2", age:"asd2"}, {name:"sweds2", age:"accxsd2"}, {name:"sdqws2", age:"asssd2"}];
var result = array.reduce((a, c) => {
if (typeof c === 'string') {
a[c] = [];
a.current = c;
} else if (a.current !== "") {
a[a.current].push(c);
}
return a;
}, {current: ""});
delete result.current;
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
How can I adjust to a particular String value, like if my input id 'city3', I need to get all elements between 'city3' and its next string value
The above approach groups the elements by the previously found string element, so you can directly access the desired target City3
var array = [ "City1", {name:"sds", age:"asd"}, {name:"sweds", age:"accxsd"}, {name:"sdqws", age:"asssd"}, "City3", {name:"sds3", age:"asd3"}, {name:"sweds3", age:"accxsd3"}, {name:"sdqws3", age:"asssd3"}, "City4", {name:"sds4", age:"asd4"}, {name:"sweds4", age:"accxsd4"}, {name:"sdqws4", age:"asssd"}];
var result = array.reduce((a, c) => {
if (typeof c === 'string') {
a[c] = [];
a.current = c;
} else if (a.current !== "") {
a[a.current].push(c);
}
return a;
}, {
current: ""
});
delete result.current;
var target = "City3";
// Now you have a direct access to find the desired target.
console.log(result[target]);
.as-console-wrapper { max-height: 100% !important; top: 0; }

You can just filter your array:
var arr = [
"City1",
{name:"sds", age:"asd"},
{name:"sweds", age:"accxsd"},
{name:"sdqws", age:"asssd"},
"City2"
];
var res = arr.filter(e => typeof e !== 'string');
console.log(res);
EDIT: if you want result from a specified start string, it should be:
var arr = [
"City1",
{name:"sds1", age:"asd"},
{name:"sweds1", age:"accxsd"},
{name:"sdqws1", age:"asssd"},
"City2",
{name:"sds2", age:"asd"},
{name:"sweds2", age:"accxsd"},
{name:"sdqws2", age:"asssd"},
"City3"
];
var str = 'City2';
var start = arr.indexOf(str);
var end = arr.findIndex((s, i) => typeof s === 'string' && i > start);
var res = arr.filter((e, i) => i > start && i < end);
console.log(res);

You could take a flag for filtering.
If a string is found switch the filter flag by checking the value with the wanted group 'City3'.
var array = ["City1", { name: "city1", age: 22 }, { name: "city1", age: 23 }, "City2", { name: "city2", age: 22 }, { name: "city2", age: 23 }, "City3", { name: "city3", age: 21 }, { name: "city3", age: 22 }, { name: "city3", age: 23 }, "City4", { name: "city4", age: 23 }, "City5"],
group = 'City3';
result = array.filter(
(f => v => typeof v === 'string' ? (f = v === group, false) : f)(false)
);
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Using a traditional for...loop you can use continue in the loop to progress to the next index if your condition is a match:
const data = [
"City1",
{ name:"sds", age: "asd" },
{ name: "sweds", age: "accxsd" },
{ name: "sdqws", age: "asssd" },
"City2"
]
for (let i = 0; i < data.length; i++) {
if (typeof data[i] === 'string') continue;
console.log(data[i].name)
}

Related

How to write this function with forEach?

I am trying to group the people by their age and as you can see, my code works with the reduce method. I managed to get this working but now I want to do the same with forEach method. Here's my code:
{name:'Kyle', age:42},
{name:'Suk', age:34},
{name:'Lol', age:35},
{name:'Pol', age:23},
{name:'Kol', age:23}
]
people.reduce((groupedPeople, person)=>{
const age = person.age
if(groupedPeople[age] == null) {groupedPeople[age]=[]
}
groupedPeople[age].push(person)
return groupedPeople
})
Reduce accepts initial value that you update each iteration and return. So if you wish to use forEach, just move initial value before the forEach:
const people = [{
name: 'Kyle',
age: 42
},
{
name: 'Suk',
age: 34
},
{
name: 'Lol',
age: 35
},
{
name: 'Pol',
age: 23
},
{
name: 'Kol',
age: 23
}
]
const groupedPeople = {}
people.forEach((person) => {
const age = person.age
if (groupedPeople[age] == null) {
groupedPeople[age] = []
}
groupedPeople[age].push(person)
})
console.log(groupedPeople)
However, I am not sure why you wish to do that. Code with reduce is much cleaner.
Why forEach is just reduce with an accumulative value. Might as well be "global".
var people = [
{name:'Kyle', age:42},
{name:'Suk', age:34},
{name:'Lol', age:35},
{name:'Pol', age:23},
{name:'Kol', age:23}
];
var result = people.reduce((groupedPeople, person) => {
const age = person.age
if (groupedPeople[age] == null) {
groupedPeople[age] = []
}
groupedPeople[age].push(person)
return groupedPeople
}, {}) // <---- you forgot this {}
console.log(result)
var result = {};
people.forEach(function(person) {
if (result[person.age] == null) {
result[person.age] = []
}
result[person.age].push(person)
})
console.log(result)
.as-console-wrapper {
max-height: 100%!important;
top: 0;
}

Transform an array of key/value pairs into array of objects

I need to be able to convert an array into a new array containing multiple objects. For example, if I have this array:
["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"]
I want to be able to convert it into this:
[{
"name": "Tom",
"id": "48688"
}, {
"name": "Bob"
"id": "91282"
}]
It is common to see a zip function taking a key k and a value v and create an object with them:
const zip =
(k, v) =>
({[k]: v});
zip("name", "Tom");
//=> {name: "Tom"}
If both key and value are in an array you can spread it in a zip call like that zip(...arr). Or you can modify the signature a little bit:
const zip =
([k, v]) =>
({[k]: v});
zip(["name", "Tom"]);
//=> {name: "Tom"}
If the array contains multiple pairs of keys and values then we can design a recursive version of zip:
const Nil = Symbol();
const zip =
([k = Nil, v = Nil, ...xs], o = {}) =>
k === Nil && v === Nil
? o
: zip(xs, (o[k] = v, o));
zip(["name", "Tom", "id", "48688"]);
//=> {name: "Tom", id: "48688"}
We can now think about slicing your array into chunks of equal number of pairs and apply zip to each chunk.
First let's write a slices function that will cut an array into slices of n elements:
const slices =
(xs, n, ys = []) =>
xs.length === 0
? ys
: slices(xs.slice(n), n, (ys.push(xs.slice(0, n)), ys));
slices(["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"], 4);
//=> [["name", "Tom", "id", "48688"],["name", "Bob", "id", "91282"]]
We can now apply zip to each chunk:
slices(["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"], 4)
.map(chunk => zip(chunk));
//=> [{name: "Tom", id: "48688"},{name: "Bob", id: "91282"}]
const Nil = Symbol();
const zip =
([k = Nil, v = Nil, ...xs], o = {}) =>
k === Nil && v === Nil
? o
: zip(xs, (o[k] = v, o));
const slices =
(xs, n, ys = []) =>
xs.length === 0
? ys
: slices(xs.slice(n), n, (ys.push(xs.slice(0, n)), ys));
console.log(
slices(["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"], 4)
.map(chunk => zip(chunk))
);
Use a for loop that increments its iteration by 4, like so:
let results = [];
for(let i = 0; i < array.length; i += 4) { // increment i by 4 to get to the start of the next object data
results.push({
id: array[i + 3], // array[i + 0] is the string "name", array[i + 1] is the name,
name: array[i + 1] // array[i + 2] is the string "id" and array[i + 3] is the id
});
}
Demo:
let array = ["name", "Tom", "id", "48688", "name", "Bob", "id", "91282", "name", "Ibrahim", "id", "7"];
let results = [];
for(let i = 0; i < array.length; i += 4) {
results.push({
id: array[i + 3],
name: array[i + 1]
});
}
console.log(results);
I see questions like this very, very often, so I made a little converter that accomplishes this particular goal:
// input
var inputArray = ["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"]
var sizeOfObjects = 2; // amount of entries per object
// function
function convert(array, size) {
var newArray = [] //set up an array
var res3 = array.reduce((acc, item, index) => {
if (index % 2 == 0) { // if the index is even:
acc[`${item}`] = array[index+1]; // add entry to array
}
if (Object.keys(acc).length == size) { // if the desired size has been reached:
newArray.push(acc); // push the object into the array
acc = {}; // reset the object
}
return acc; // preserve accumulator so it doesn't get forgotten
}, {}); // initial value of reducer is an empty object
return newArray; //return the array
}
console.log(convert(inputArray, sizeOfObjects));
Hopefully this helps people who are looking for an answer for this kind of question.
If you're looking to just create a single object, look at this other question/answer: Create object from array
We can use % operator to decide whether we find an object to insert into array or not:
const data = ["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"];
makeObjectArray = arr => {
const result = [], temp = [];
arr.forEach((a, i)=>{
if (i % 2 == 0)
temp.push({ [arr[i]]: arr[i + 1]})
if (i % 3 == 0 && i != 0) {
result.push(Object.assign({}, ...temp));
temp.length = 0;
}
})
return result;
}
console.log(makeObjectArray(data))
you can break the array into smaller chunks of the desired size with a helper function like:
function chunk(to_chunk, chunk_size) {
var output = [];
if(to_chunk.length > chunk_size) {
output.push(to_chunk.slice(0, chunk_size));
output.push(chunk(to_chunk.slice(chunk_size)));
return output;
} else {
return to_chunk;
}
}
Then you can map the result with other function to return your desired object:
var final = chunk(seed, 4).map((x) => myObject(x));
function myObject(seed) {
var output = {};
output[seed[0]] = seed[1];
output[seed[2]] = seed[3];
return output;
}
I think this approach is nice in terms of readability, putting all together you have:
var seed = ["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"];
var final = chunk(seed, 4).map((x) => myObject(x));
console.log(final);
function chunk(to_chunk, chunk_size)
{
var output = [];
if(to_chunk.length > chunk_size) {
output.push(to_chunk.slice(0, chunk_size));
output.push(chunk(to_chunk.slice(chunk_size)));
return output;
} else {
return to_chunk;
}
}
function myObject(seed)
{
var output = {};
output[seed[0]] = seed[1];
output[seed[2]] = seed[3];
return output;
}
You could take a dynamic approach by using an object for keeping track of the target index for same named keys.
const
getArray = data => {
let indices = {},
result = [],
i = 0;
while (i < data.length) {
const [key, value] = data.slice(i, i += 2);
indices[key] ??= 0;
(result[indices[key]++] ??= {})[key] = value;
}
return result;
},
data1 = ["name", "Tom", "id", "48688", "name", "Bob", "id", "91282"],
data2 = ["name", "Tom", "id", "48688", "color", "green", "name", "Bob", "id", "91282", "color", "red"];
console.log(getArray(data1));
console.log(getArray(data2));
.as-console-wrapper { max-height: 100% !important; top: 0; }

How to convert object properties string to integer in javascript

I would like to know how to convert object properties string to integer in javascript.
I have a obj, which if has property value is number string convert to number in javascript
var obj={
ob1: {id: "21", width:"100",height:"100", name: "image1"},
ob2: {id: "22", width:"300",height:"200", name: "image2"}
}
function convertIntObj (obj){
Object.keys(obj).map(function(k) {
if(parseInt(obj[k])===NaN){
return obj[k]
}
else{
return parseInt(obj[k]);
}
});
}
var result = convertIntObj(obj);
console.log(result)
Expected Output:
[
{id: 21, width:100,height:100, name: "image1"},
{id: 22, width:300,height:200, name: "image2"}
]
This should do the work:
var obj = {
ob1: {
id: "21",
width: "100",
height: "100",
name: "image1"
},
ob2: {
id: "22",
width: "300",
height: "200",
name: "image2"
}
}
function convertIntObj(obj) {
const res = {}
for (const key in obj) {
res[key] = {};
for (const prop in obj[key]) {
const parsed = parseInt(obj[key][prop], 10);
res[key][prop] = isNaN(parsed) ? obj[key][prop] : parsed;
}
}
return res;
}
var result = convertIntObj(obj);
console.log('Object result', result)
var arrayResult = Object.values(result);
console.log('Array result', arrayResult)
Click "Run code snippet" so see the result
Iterating over Object.keys() twice. If the value corresponding to the key is a number then parseInt the value else set the default value which was present earlier
var obj = {
ob1: { id: "21", width: "100", height: "100", name: "image1" },
ob2: { id: "22", width: "300", height: "200", name: "image2" }
};
var res = {};
Object.keys(obj).forEach(key => {
res[key] = {};
Object.keys(obj[key]).forEach(temp => {
res[key][temp] = !isNaN(obj[key][temp])
? parseInt(obj[key][temp], 10)
: obj[key][temp];
});
return res;
});
console.log(res);
.as-console-wrapper { max-height: 100% !important; top: 0; }
You can use Object.entries() and .reduce() methods to iterate over the key value pairs in your data and use Number and Number.isNaN() methods to transform the values appropriately.
const data = {
ob1: {id: "21", width:"100",height:"100", name: "image1"},
ob2: {id: "22", width:"300",height:"200", name: "image2"}
};
const result = Object.entries(data).reduce((r, [k, o]) => {
r[k] = Object.entries(o).reduce((r, [k, v]) => {
let _v = Number(v);
if(!Number.isNaN(_v)) { v = _v; }
return (r[k] = v, r);
}, {});
return r;
}, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
Hi I would recommend you to use the JSON.stringify() method. It is used to convert object to string which is needed to send data over the web server. It converts the set of variables in the object to a JSON string:
var objToStr = {
siteName: "W3Docs",
bookName: "Javascript",
booksCount: 5
};
var myJSON = JSON.stringify(objToStr);
console.log(myJSON);
Also, you can use the The toString() method. It is also called when you need to convert the object into a string:
var obj = {
siteName: "W3Docs",
bookName: "Javascript",
booksCount: 5
};
function objToString(object) {
var str = '';
for (var k in object) {
if (object.hasOwnProperty(k)) {
str += k + '::' + object[k] + '\n';
This information is taken from this source.

filter array of object base on array of object

This is my data
[{name:'james',grade:'A'},
{name:'john',grade:'B'},
{name:'iris',,grade:'A'},
{name:'ivan',,grade:'C'}]
I want to keep object that has grade A and C, it's easy I can just do filter like
person.filter(obj => obj.grade === 'A' || obj.grade === 'C')
but now I have an array of object.
[{grade:'A'},{grade:'C'}]
any clue how can I do filtering now? do I need nested loop?
Use Array.prototype.some:
let person = [{name:'james', grade:'A'},
{name:'john', grade:'B'},
{name:'iris', grade:'A'},
{name:'ivan', grade:'C'}];
let predicate = [{grade:'A'},{grade:'C'}];
let result = person.filter(obj => predicate.some(p => p.grade == obj.grade))
console.log('result:', result)
If your predicate is more dynamic than that, compare all object properties instead of just p.grade.
person.filter(obj => predicate.some(p => {
return Object.keys(p).every(k => obj[k] == p[k]);
}));
Using underscore lib
eg -
var bbb = [
{id: 839},
{id: 854}
];
var ids = {};
_.each(bbb, function (bb) { ids[bb.id] = true; });
var data = [{grade:'A'},{grade:'C'}];
var value = {};
_.each(data , function (d) { value[data.garde] === 'A' | value[data.garde] === 'C' ; });
Objects having grades A and C should be filtered as (classic js syntax),
var a = [
{name:'james',grade:'A'},
{name:'john',grade:'B'},
{name:'iris',grade:'A'},
{name:'ivan',grade:'C'}
];
a.filter(function(e) {
return (e.grade == 'A') || (e.grade == 'C');
});
If you have many grades to check (I don't know like all of them ;) ). You could first convert array into Set
const grades = new Set([{grade:'A'},{grade:'C'}].map(({grade}) => grade))
const persons = [{name:'james',grade:'A'},
{name:'john',grade:'B'},
{name:'iris',grade:'A'},
{name:'ivan',grade:'C'}]
And then filter persons array using has
const filtered = persons.filter(({grade}) => grades.has(grade))
You could use a Set for the predicates and filter accordingly
let person = [{ name: 'james', grade: 'A' }, { name: 'john', grade: 'B' }, { name: 'iris', grade: 'A' }, { name: 'ivan', grade: 'C' }],
predicate = [{ grade: 'A' }, { grade: 'C' }],
result = person.filter((s => p => s.has(p.grade))(new Set(predicate.map(p => p.grade))));
console.log(result)
.as-console-wrapper { max-height: 100% !important; top: 0; }

how to re position the key of an object in a JSON using jquery or javascript

I have two objects which I need to compare. However there is a problem in the position of the keys in an object.
var obj1 = [{
Name : abc;
age : 23;
}, {
Name : def;
age : 222;
}]
var obj2 = [{
age : 23;
Name: abc;
}, {
age : 222;
Name : def;
}]
I have tried using the below, but it failed.
(JSON.stringify(obj1) == JSON.stringify(obj2))
Is there a way to swap the position of the keys in an object which iterates throughout the object? I am expecting something like this
var obj1 = [{
Name : abc;
age : 23;
}, {
Name : def;
age : 222;
}]
var obj2 = [{
Name : abc;
age : 23;
}, {
Name : def;
age : 222;
}]
The keys of an object (unordered) is different from the index of an array (ordered). To compare two arrays of objects and see if they have the same object (with the same key/value pairs) in each of the array elements, you can try this:
function compareArrayOfObjects(array1, array2) {
return array1.reduce(function(bool, obj, index) {
return bool && array2[index] && isEqual(obj, array2[index]);
}, array1.length === array2.length);
}
If you simply need to compare values as simple as numbers and strings, you can implement isEqual() as follows:
function isEqual(a, b) {
var aKeys = Object.getOwnPropertyNames(a);
var bKeys = Object.getOwnPropertyNames(b);
return aKeys.reduce(function(bool, aKey) {
return bool && (a[aKey] === b[aKey]);
}, aKeys.length === bKeys.length);
}
If you need deep object comparisons then you probably want a LoDash implementation of _.isEqual().
To put it all together, you will have
var obj1 = [{
Name: 'abc',
age: 23
}, {
Name: 'def',
age: 222
}];
var obj2 = [{
age: 23,
Name: 'abc'
}, {
age: 222,
Name: 'def'
}];
var obj3 = [{}, {}];
function compareArrayOfObjects(array1, array2) {
return array1.reduce(function(bool, obj, index) {
return bool && array2[index] && isEqual(obj, array2[index]);
}, array1.length === array2.length);
}
function isEqual(a, b) {
var aKeys = Object.getOwnPropertyNames(a);
var bKeys = Object.getOwnPropertyNames(b);
return aKeys.reduce(function(bool, aKey) {
return bool && (a[aKey] === b[aKey]);
}, aKeys.length === bKeys.length);
}
console.log('obj1 and obj2 is the same (expected true): ' + compareArrayOfObjects(obj1, obj2));
console.log('obj1 and obj3 is the same (expected false): ' + compareArrayOfObjects(obj1, obj3));
As #RoryMcCrossan said -
The order of the keys in an object is not guaranteed
You should use this code instead
var obj1 = [{
Name: 'abc',
age: 23
}, {
Name: 'def',
age: 222
}];
var obj2 = [{
age: 23,
Name: 'abc'
}, {
age: 222,
Name: 'def'
}];
function isEqual(objA, objB) {
if (objA.length !== objB.length)
return false;
let isequal = true;
for (let i = 0; i < objA.length; i++) {
if (objA[i].Name !== objB[i].Name || objA[i].age !== objB[i].age)
isequal = false;
}
return isequal;
}
if(isEqual(obj1, obj2)){
console.log("Equal");
}else{
console.log("Not equal");
}
The order of the keys in an object is not guaranteed, so any attempt to rearrange them would be redundant.
However given your description, this seems to be an XY problem, as your goal is to compare the objects. The issue you have is that objects cannot be directly compared. Instead, compare their properties, eg.
if (obj1[i].Name == obj2[i].Name && obj1[i].age == obj2[i].age) {
// do something...
}
Well, as all the other answer already tell you, you'll have to compare the keys, not the objects themselves. Just adding another implementation
function isObject(value) {
return typeof value === "object" && value !== null;
}
function isSimilar(a, b) {
if (a === b) return true;
return isObject(a) && isObject(b) &&
Object.keys(a).every(key => a[key] === undefined || key in b && isSimilar(a[key], b[key])) &&
Object.keys(b).every(key => b[key] === undefined || key in a);
}
var obj1 = [{
Name: 'abc',
age: 23,
thisKeyIsIgnoredSinceItIsUndefined: undefined
}, {
Name: 'def',
age: 222
}];
var obj2 = [{
age: 23,
Name: 'abc'
}, {
age: 222,
Name: 'def'
}];
console.log(isSimilar(obj1, obj2))
well there is better way though examples above will work but they will fail for unknown keys.
function compareArrayObjects(ob1, ob2) {
let ob1Keys = Object.keys(ob1);
let ob2Keys = Object.keys(ob2);
return (ob1Keys.length == ob2Keys.length?(ob1Keys.every(key)=>(obj1[key]==ob2[key]))
:false);
}
or 1 line solution will be
_.intersection(obj1,obj2);

Categories

Resources