I have this JSON string:
[
{
"pk": "alpha",
"item": [{
"child": "val"
}]
},
{
"pk": "beta",
"attr": "val",
"attr2": [
"child1"
]
},
{
"pk": "alpha",
"anotherkey": {
"tag": "name"
}
}
]
And I need to produce a filtered array without repeated PK, in the example above the last entry: "pk": "alpha","anotherkey": { ... should be eliminated from the output array. All this using JavaScript. I tried with the object JSON.parse but it returns many key,value pairs that are hard to filter for example "key=2 value=[object Object]".
Any help is greatly appreciated.
var data = JSON.parse(jsonString);
var usedPKs = [];
var newData = [];
for (var i = 0; i < data.length; i++) {
if (usedPKs.indexOf(data[i].pk) == -1) {
usedPKs.push(data[i].pk);
newData.push(data[i]);
}
}
// newData will now contain your desired result
var contents = JSON.parse("your json string");
var cache = {},
results = [],
content, pk;
for(var i = 0, len = contents.length; i < len; i++){
content = contens[i];
pk = content.pk;
if( !cache.hasOwnPropery(pk) ){
results.push(content);
cache[pk] = true;
}
}
// restuls
<script type="text/javascript">
// Your sample data
var dataStore = [
{
"pk": "alpha",
"item": [{
"child": "val"
}]
},
{
"pk": "beta",
"attr": "val",
"attr2": [
"child1"
]
},
{
"pk": "alpha",
"anotherkey": {
"tag": "name"
}
}
];
// Helper to check if an array contains a value
Array.prototype.contains = function(obj) {
var i = this.length;
while (i--) {
if (this[i] == obj) {
return true;
}
}
return false;
}
// temp array, used to store the values for your needle (the value of pk)
var tmp = [];
// array storing the keys of your filtered objects.
var filteredKeys = [];
// traversing you data
for (var i=0; i < dataStore.length; i++) {
var item = dataStore[i];
// if there is an item with the same pk value, don't do anything and continue the loop
if (tmp.contains(item.pk) === true) {
continue;
}
// add items to both arrays
tmp.push(item.pk);
filteredKeys.push(i);
}
// results in keys 0 and 1
console.log(filteredKeys);
</script>
Related
I'm using jsTree and have tree an structured JSON object.
[{
"id": 1,
"text": "TEXT_ONE",
"children": [
{
"id": 2,
"text": "TEXT_TWO",
"children": [
{
"id": 3,
"text": "TEXT_THREE",
"children": [
]
},
{
"id": 4,
"text": "TEXT_FOUR",
"children": [
]
}
]
},
{
"id": 5,
"text": "TEXT_FIVE",
"children": [
]
}
]
},
{
"id": 6,
"text": "TEXT_SIX",
"children": [ ]
}]
I want to get the the object based on the "id" of the object.
For example if i have a function getIdFromTree(3) it will return me the JSON object as following:
{
"id": 3,
"text": "TEXT_THREE",
"children": []
},
How I do that in Javascript/JQuery?
Try this
function getObjById (tree, id) {
if(tree.id === id) {
return tree;
}
if(tree.children) {
for(var i = 0, l = tree.children.length; i < l; i++) {
var returned = getObjById(tree.children[i], id);
if(returned) {
// so that the loop doesn't keep running even after you find the obj
return returned;
}
}
}
}
Call this as follows
getObjById({children: tree}, 3); // tree is the array object above.
function findById (tree, id) {
var result, i;
if (tree.id && tree.id === id) {
result = tree;
// Revalidate array list
} else if (tree.length) {
for (i = 0; i < tree.length; i++) {
result = findById(tree[i], id);
if (result) {
break;
}
}
// Check childrens
} else if (tree.children) {
result = findById(tree.children, id);
}
return result;
}
Use filter Methode off Array
data.filter(function (obj){ obj.id== 3});
try this.... Es6
function *getObjectById(data, id) {
if (!data) return;
for (let i = 0; i< data.length; i++){
let val = data[i];
if (val.id === id) yield val;
if (val.children) yield *getObjectById(val.children , id);
}
}
now
getObjectById(arrayOfObjects, id).next().value;
try this with most effective and efficient way..
function getObjById (tree, id) {
for(var i= 0;i<tree.length;i++)
{
if(tree[i].id===id)
{
return tree[i];
}
if(tree[i].children)
{
var returned = getObjById(tree[i].children,id);
if(returned!= undefined)
return returned;
}
}
};
link:
https://jsfiddle.net/aa7zyyof/14/
I have an object in this format:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
I want to transform it into this:
var request = {
"student": [
{
"name": "Tom",
"age": 12
},
{
"name": "Jack",
"age": 13
}
]
}
I tried doing it this way:
var response = [];
var keysCount = req.result[0].length;
var responseCount = req.result.length - 1;
var i = 0,
j = 0,
key;
for (j = 0; j < responseCount; j++) {
for (i = 0; i < keysCount; i++) {
key = req.result[0][i];
response[j][key] = req.result[j + 1][i];
}
}
return response;
But, it is not working as expected.
It's a matter of looping through the first array and creating an array of objects for all the remaining arrays, using values at matching indexes to create properties on object:
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// Get the header array
var headers = request.student[0];
// Create the new array but mapping the other entries...
var newArray = request.student.slice(1).map(function(entry) {
// Create an object
var newEntry = {};
// Fill it in with the values at matching indexes
headers.forEach(function(name, index) {
newEntry[name] = entry[index];
});
// Return the new object
return newEntry;
});
console.log(newArray);
I would make a small function tabularize that takes an array of data where the first element is an array of headers, and the remaining elements are the rows
Code that follows uses ES6. If you need ES5 support, you can safely transpile this code using a tool like babel.
// your original data
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your transformed object
var request2 = {student: tabularize(request.student)};
// log the output
console.log(request2);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Or you can create the request object with the intended shape by passing the tabular data directly into the tabularize function at the time of object creation
// tabularize function
var tabularize = ([headers, ...rows])=>
rows.map(row=>
headers.reduce((acc,h,i)=>
Object.assign(acc, {[h]: row[i]}), {}));
// your request object
var request = {
student: tabularize([
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
])
};
// log the output
console.log(request);
//=> {"student":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Let's start off by writing a little function just to create an object from two arrays, one of keys and one of their values:
function makeObjectFromPairs(keys, values) {
var object = {};
for (var i = 0; i < keys.length; i++) {
object[keys[i]] = values[i];
}
return object;
}
// makeObjectFromPairs(['a', 'b'], [1, 2]) === {a: 1, b: 2}
Now we can use the first element of the students array as the keys, and each of the remaining elements as the values.
var keys = students[0];
var result = [];
for (var i = 1; i < students.length; i++) {
result.push(makeObjectFromPairs(keys, students[i]);
}
You could use Array#map etc. as an alternative for the loops, but perhaps this basic approach is more accessible.
Fixing your original code
Since you made a valiant effort to solve this yourself, let's review your code and see where you went wrong. The key point is that you are not initializing each element in your output to an empty object before starting to add key/value pairs to it.
for (j = 0; j < responseCount; j++) {
// Here, you need to initialize the response element to an empty object.
response[j] = {};
Another solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var response = {};
var students = [];
var responseCount = request.student.length - 1;
var j = 0,
key;
for (j = 0; j < responseCount; j++) {
var student = {};
request.student[0].forEach(function(name, index) {
student[name] = request.student[1 + j][index];
});
students.push(student)
}
response["students"] = students;
console.log(response); // {"students":[{"name":"Tom","age":12},{"name":"Jack","age":13}]}
Lodash solution
var keys = _.head(request.student);
var valueGroups = _.flatten(_.zip(_.tail(request.student)));
var studentObjects = valueGroups.map(function(values){
return values.reduce(function(obj, value, index){
obj[keys[index]] = value;
return obj;
}, {});
});
console.log(studentObjects);
https://jsfiddle.net/mjL9c7wt/
Simple Javascript solution :
var request = {
"student": [
[
"name",
"age"
],
[
"Tom",
12
],
[
"Jack",
13
]
]
};
var students = [];
for(var x = 1; x<request.student.length;x++)
{
var temp = { 'name' : request.student[x][0],
'age' : request.student[x][1]
}
students.push(temp);
}
request = { 'students' : students}
console.log(request);
I have the following two arrays:
var data1=[
{
"id": 1,
"url": "http://192.168.1.165:90/asset/"
},
{
"id": 2,
"url": "Assigned"
}
]
var data2=[
{
"id": 1,
"url": "http://192.168.1.165:90/asset/"
},
{
"id": 2,
"url": "Assigned"
},
{
"id": 3,
"url": "Assigned"
}
]
Result:
var unique=[{ {
"id": 3,
"url": "Assigned"
}}]
How can I get the unique object from these two arrays ?
I have tried using a for loop like this :
var unique = [];
for(var i = 0; i < data2.length; i++){
var found = false;
for(var j = 0; data1.length; j++){
if(data2[i].id == data1[j].id){
found = true;
break;
}
}
if(found == false){
unique.push(array1[i]);
}
}
But wanted to get a solution using functional javascript...
Try like this
var joined = data1.concat(data2);
var temp = [];
joined.forEach(function (x) {
var objList=joined.filter(function(y){ return y.id == x.id});
if(objList.length == 1) // if data count of current item in merged array is 1 that's means it belong to only one data source
temp.push(x);
})
console.log(temp)
JSFIDDLE
try this: first get the objects from data1 which are not in data2 and remove from data2 if it is there then concat it with data2.
<script>
var data1=[
{
"id": 1,
"url": "http://192.168.1.165:90/asset/"
},
{
"id": 2,
"url": "Assigned"
}
];
var data2=[
{
"id": 1,
"url": "http://192.168.1.165:90/asset/"
},
{
"id": 2,
"url": "Assigned"
},
{
"id": 3,
"url": "Assigned"
}
];
var arr3 = [];
for(var i in data1){
var dup = false;
for (var j in data2){
if (data2[j].id == data1[i].id && data2[j].url == data1[i].url) {
data2.splice(j,1);
}
}
if(dup) arr3.push(arr1[i])
}
arr3 = arr3.concat(data2);
console.log(arr3);
</script>
Edited for resulting the single unique object!
Assuming you have a function:
function unique(arr) {
var uni = [];
for(var i=0; i<arr.length; ++i) {
var rep = -1;
for(var j=0; j<arr.length; ++j)
if(arr[i].id == arr[j].id) rep++;
if (!rep) uni.push(arr[i]);
}
return uni;
}
this would work and give you the single unique object:
var u = unique(data1.concat(data2));
The idea is to make an union of the two given arrays and then iterate through setA and look for the matching properties and values in setA and in union. If found, then the index is stored. If there are more than one index, delete all items from union whith the indices.
The rest is then the symmetric difference.
var data1 = [{ "id": 1, "url": "http://192.168.1.165:90/asset/" }, { "id": 2, "url": "Assigned" }],
data2 = [{ "id": 1, "url": "http://192.168.1.165:90/asset/" }, { "id": 2, "url": "Assigned" }, { "id": 3, "url": "Assigned" }];
function symmetricDifference(setA, setB) {
var union = setA.concat(setB);
setA.forEach(function (a) {
var aK = Object.keys(a),
indices = [];
union.forEach(function (u, i) {
var uK = Object.keys(u);
aK.length === uK.length &&
aK.every(function (k) { return a[k] === u[k]; }) &&
indices.push(i);
});
if (indices.length > 1) {
while (indices.length) {
union.splice(indices.pop(), 1);
}
}
});
return union;
}
document.write('<pre>' + JSON.stringify(symmetricDifference(data1, data2), 0, 4) + '</pre>');
This is making my head hurt, if there are any generous javascript gurus here, i would greatly appreciate some help
What I'm trying to achieve is this:
Given this:
var keys = ["Age", "Name", "Photos", { "Friends": ["FirstName", "LastName"] }];
var values = [ [31, "Bob", ["1.jpg", "2.jpg"], [ ["Bob", "Hope"], ["Foo", "Bar"] ] ], [21, "Jane"] ["4.jpg", "5.jpg"], [ ["Mr", "T"],["Foo", "Bar"] ] ];
I would like to get back this:
var object = [
{
"Age" : 31,
"Name" : "Bob",
"Photos" : ["1.jpg", "2.jpg"]
"Friends": [
{
"FirstName": "Bob",
"LastName" : "Hope"
},
{
"FirstName": "Foo",
"LastName" : "Bar"
}
]
},
{
"Age" : 21,
"Name" : "Jane",
"Photos" : ["4.jpg", "5.jpg"]
"Friends": [
{
"FirstName": "Mr",
"LastName" : "T"
},
{
"FirstName": "Foo",
"LastName" : "Bar"
}
]
}
];
It's for a spec proposal (JsonR) i'm working on here
Currently i'm able to (almost) work this out (but not any deeper..):
var keys = ["Age", "Name", "Photos" ];
var values = [ [31, "Bob", ["1.jpg", "2.jpg"]], [21, "Jane", ["4.jpg", "5.jpg"]] ];
Thank's for any feedback or help!
Here's a function that does what I think you want:
function keyValuesToObject(keys, values) {
var obj = [];
for (var i = 0; i < values.length; i++) {
var value = values[i];
obj.push({});
for (var j = 0; j < value.length; j++) {
var key = keys[j];
if (typeof key === "object") {
for (var k in key) {
obj[i][k] = keyValuesToObject(key[k], value[j]);
}
}
else {
obj[i][key] = value[j];
}
}
}
return obj;
};
It does not handle malformed input, so you might want to put checks in there depending on how you plan to use it.
You can see it in action on this online jsFiddle demo.
By the way, the key and value value arrays you gave had mismatched opening and closing brackets, so I had to fix them.
Fiddle
function pairUpItem(keys, values) {
var len = keys.length;
var result = {};
for (var i = 0; i < len; i++) {
var key = keys[i];
var value = values[i];
if (typeof(key) == "string") {
result[key] = value;
} else {
for (var key2 in key) {
if (key.hasOwnProperty(key2)) {
result[key2] = pairUpItems(key[key2], value);
}
}
}
}
return result;
}
function pairUpItems(keys, values) {
var len = values.length;
var result = [];
for (var i = 0; i < len; i++) {
var value = values[i];
if (typeof(value) !== "undefined") {
result.push(pairUpItem(keys, value));
}
}
return result;
}
var keys = ["Age", "Name", "Photos", { "Friends": ["FirstName", "LastName"] }];
var values = [ [31, "Bob", ["1.jpg", "2.jpg"], [ ["Bob", "Hope"], ["Foo", "Bar"] ] ], [21, "Jane", ["4.jpg", "5.jpg"], [ ["Mr", "T"],["Foo", "Bar"] ] ] ];
var result = pairUpItems(keys, values);
console.dir(result);
I have a JSON data structure as shown below:
{
"name": "World",
"children": [
{ "name": "US",
"children": [
{ "name": "CA" },
{ "name": "NJ" }
]
},
{ "name": "INDIA",
"children": [
{ "name": "OR" },
{ "name": "TN" },
{ "name": "AP" }
]
}
]
};
I need to change the key names from "name" & "children" to say "key" & "value". Any suggestion on how to do that for each key name in this nested structure?
I don't know why you have a semicolon at the end of your JSON markup (assuming that's what you've represented in the question), but if that's removed, then you can use a reviver function to make modifications while parsing the data.
var parsed = JSON.parse(myJSONData, function(k, v) {
if (k === "name")
this.key = v;
else if (k === "children")
this.value = v;
else
return v;
});
DEMO: http://jsfiddle.net/BeSad/
Try this:
function convert(data){
return {
key: data.name,
value: data.children.map(convert);
};
}
Or if you need to support older browsers without map:
function convert(data){
var children = [];
for (var i = 0, len = data.children.length; i < len; i++){
children.push(convert(data.children[i]));
}
return {
key: data.name,
value: children
};
}
You could use a function like this :
function clonerename(source) {
if (Object.prototype.toString.call(source) === '[object Array]') {
var clone = [];
for (var i=0; i<source.length; i++) {
clone[i] = goclone(source[i]);
}
return clone;
} else if (typeof(source)=="object") {
var clone = {};
for (var prop in source) {
if (source.hasOwnProperty(prop)) {
var newPropName = prop;
if (prop=='name') newPropName='key';
else if (prop=='children') newPropName='value';
clone[newPropName] = clonerename(source[prop]);
}
}
return clone;
} else {
return source;
}
}
var B = clonerename(A);
Note that what you have isn't a JSON data structure (this doesn't exist as JSON is a data-exchange format) but probably an object you got from a JSON string.