Sort an array of objects by an objects value - ios

I have an array of objects that I parse from a JSON. My JSON looks like this;
- message: [
-{
movie_id: 30,
movie_name: "Scream",
category_name: "Horror"
},
-{
movie_id: 31,
movie_name: "Avengers",
category_name: "Action"
},
-{
movie_id: 32,
movie_name: "Friday the 13th",
category_name: "Horror"
},
-{
movie_id: 33,
movie_name: "The ring",
category_name: "Horror"
},
-{
movie_id: 34,
movie_name: "Die Hard",
category_name: "Action"
},
-{
movie_id: 35,
movie_name: "The ring 2",
category_name: "Horror"
},
....
Its a JSON array of movies that contains many movies. What I am unable to do is parse each object and arrange them by category_name in an array, so all the "horror" will be grouped together, all the action, and all the romance etc etc. However...I need to be able to place a String value at the start of each category. So the array might look like this:
Index
0 "Horror"
1 Movie Object
2 Movie Object
3 Movie Object
4 "Romance"
5 Movie Object
6 Movie Object
7 "Action"
8 Movie Object
9 Movie Object
10 Movie Object
I have movie object with the following paramters;
NSString *movie_id
NSString * movie_name
NSString *category_name
Any help is greatly appreciated.

I would suggest a slightly different structure for the parsed data.
Rather than an array of mixed strings and objects, why not create a dictionary (using the category names as keys) of arrays? Just iterate through your original JSON. For each movie object, check to see if the key exists for that category name. If it does not, add a new array as the value for that category name. Then add the movie object to the array.
Your final dictionary would be something like this:
#{ #"Horror" : #[obj1, obj2, obj 3],
#"Romance" : #[obj4, obj5, obj 6],
#"Action" : #[obj7, obj8, obj 9] }
That way you can iterate through each category, and also iterate through the movies is each category

Suppose You have your array message then you can arrange them as
NSArray *categories = [message valueForKeyPath:#"#distinctUnionOfObjects.category_name"];
NSMutableArray *results = [NSMutableArray new];
for (NSString *categoryName in categories)
{
NSArray *groupArray = [message filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category_name = %#", categoryName]];
[results addObject:categoryName];
[results addObjectsFromArray:groupArray];
}
and your final array I mean results will be
(
Horror,
{
"category_name" = Horror;
"movie_id" = 30;
"movie_name" = Scream;
},
{
" movie_name" = "Friday the 13th";
"category_name" = Horror;
"movie_id" = 32;
},
{
"category_name" = Horror;
"movie_id" = 33;
"movie_name" = "The ring";
},
{
"category_name" = Horror;
"movie_id" = 35;
"movie_name" = "The ring 2";
},
Action,
{
"category_name" = Action;
"movie_id" = 31;
"movie_name" = Avengers;
},
{
"category_name" = Action;
"movie_id" = 34;
"movie_name" = "Die Hard";
}
)
Hope this is what you want.
But this not a good coding practice, to have different data types(string and dictionary) in same array. so you should parse them like this
NSArray *categories = [message valueForKeyPath:#"#distinctUnionOfObjects.category_name"];
NSMutableDictionary *results = [NSMutableDictionary new];
for (NSString *categoryName in categories)
{
NSArray *groupArray = [message filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"category_name = %#", categoryName]];
[results setObject:groupArray forKey:categoryName];
}
and your result will be.
{
Action = (
{
"category_name" = Action;
"movie_id" = 31;
"movie_name" = Avengers;
},
{
"category_name" = Action;
"movie_id" = 34;
"movie_name" = "Die Hard";
}
);
Horror = (
{
"category_name" = Horror;
"movie_id" = 30;
"movie_name" = Scream;
},
{
" movie_name" = "Friday the 13th";
"category_name" = Horror;
"movie_id" = 32;
},
{
"category_name" = Horror;
"movie_id" = 33;
"movie_name" = "The ring";
},
{
"category_name" = Horror;
"movie_id" = 35;
"movie_name" = "The ring 2";
}
);
}
Now choose whatever you want.

Related

Merge object and add keys from JSON format using Ruby on Rails

I have a list of array that is queried that needs to be merged with the same location_id based on the objects.
**this are the code for generating array **
filled = Product.on_hand_location(pid).to_a
empty = Product.on_hand_location_empty_cylinder(pid).to_a
data = filled + empty
result = data.map{ |k|
{
details: {
location_id: k['location_id'],
"location_name"=>k['location_name'],
"onhandcylynder"=>k['onhand'] == nil ? 0 : k['onhand'],
"emptycylynder"=> k['emptyonhand'] == nil ? 0 : k['emptyonhand']
} ,
}
}
respond_with [ onhand: result ]
This JSON format below is the output of code above. which has location_id that needs to be merge
[{
"onhand": [{
"details": {
"location_id": 1,
"location_name": "Capitol Drive",
"onhandcylynder": "4.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 2,
"location_name": "SM City Butuan",
"onhandcylynder": "5.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 1,
"location_name": null,
"onhandcylynder": 0,
"emptycylynder": "2.0"
}
}
]
}]
My desired output
[{
"onhand": [{
"details": {
"location_id": 1,
"location_name": "Capitol Drive",
"onhandcylynder": "4.0",
"emptycylynder": 0
}
},
{
"details": {
"location_id": 2,
"location_name": "SM City Butuan",
"onhandcylynder": "5.0",
"emptycylynder": "2.0"
}
}
]
}]
I think instead of data = filled + empty you should try
data = Product.on_hand_location(pid).to_a
empty = Product.on_hand_location_empty_cylinder(pid).to_a
empty.each do |location|
data.push(location) if data.none? { |item| item['location_id'] == product['location_id'] }
end
result = ...
or
hash = {}
Product.on_hand_location_empty_cylinder(pid).map { |l| hash[l['location_id']] = l }
Product.on_hand_location(pid).map { |l| hash[l['location_id']] = l }
data = hash.values
and if you need some data from both of the queries you should try
hash = {}
Product.on_hand_location_empty_cylinder(pid).map { |l| hash[l['location_id']] = l }
Product.on_hand_location(pid).map { |l| hash[l['location_id']].merge!(l) }
data = hash.values
to merge in place
I refactor my code and able to get my desired result
filled = Product.on_hand_location(pid).to_a
emptyTank = Product.on_hand_location_empty_cylinder(pid).to_a
data = filled + emptyTank
cylinder = data.map(&:dup)
.group_by { |e| e.delete('location_id') }
finalResult = cylinder.map{|_, location_id | location_id.reduce({}) { |result, location_id|
result.merge(location_id)
} }
respond_with [ onhand: finalResult]
The result already merge with the same location id and emptyonhand keys are merge already in corresponding to its location ID
[
{
"onhand": [
{
"onhand": "1.0",
"location_name": "Capitol Drive",
"emptyonhand": "5.0"
},
{
"onhand": "5.0",
"location_name": "SM City Butuan"
}
]
}
]

Robot allowed the website but being identified and rejected

I need to do web scraping for a website which has allowed robot access. Below is the robot.txt file's content.
User-agent: *
Disallow:
Sitemap:https://www.sample.com/sitemap-index.xml
But when I try to fetch the website's content using nokogiri, it's being detected.
Nokogiri::HTML(open('https://www.sample.com/search?q=test', :ssl_verify_mode => OpenSSL::SSL::VERIFY_NONE))
Here the output:
> (Document:0x3fda40e7cf70 {
name = "document",
children = [
#(DTD:0x3fda40e9591c { name = "html" }),
#(Element:0x3fda40e8c95c {
name = "html",
attributes = [ #(Attr:0x3fda4071a598 { name = "style", value = "height:100%" })],
children = [
#(Element:0x3fda3fefa28c {
name = "head",
children = [
#(Element:0x3fda401a3088 {
name = "meta",
attributes = [ #(Attr:0x3fda40ebd7a0 { name = "name", value = "ROBOTS" }), #(Attr:0x3fda40ebd778 { name = "content", value = "NOINDEX, NOFOLLOW" })]
}),
#(Element:0x3fda4074faf4 {
name = "meta",
attributes = [ #(Attr:0x3fda3ff0beec { name = "name", value = "format-detection" }), #(Attr:0x3fda3ff0bed8 { name = "content", value = "telephone=no" })]
}),
#(Element:0x3fda401ca700 {
name = "meta",
attributes = [ #(Attr:0x3fda401c2050 { name = "name", value = "viewport" }), #(Attr:0x3fda401c217c { name = "content", value = "initial-scale=1.0" })]
}),
#(Element:0x3fda4079a284 {
name = "meta",
attributes = [ #(Attr:0x3fda4078bfb8 { name = "http-equiv", value = "X-UA-Compatible" }), #(Attr:0x3fda4078bf04 { name = "content", value = "IE=edge,chrome=1" })]
})]
}),
#(Element:0x3fda407e2e6c {
name = "body",
attributes = [ #(Attr:0x3fda430205f0 { name = "style", value = "margin:0px;height:100%" })],
children = [
#(Element:0x3fda4072e2a0 {
name = "iframe",
attributes = [
#(Attr:0x3fda3ff45214 {
name = "src",
value = "/_Incapsula_Resource?SWUDNSAI=28&xinfo=5-66719320-0%200NNN%20RT%281543054979096%20247%29%20q%280%20-1%20-1%20-1%29%20r%280%20-1%29%20B12%284%2c315%2c0%29%20U2&incident_id=245000650118470008-256430953704260629&edet=12&cinfo=04000000"
}),
#(Attr:0x3fda3ff451d8 { name = "frameborder", value = "0" }),
#(Attr:0x3fda3ff451b0 { name = "width", value = "100%" }),
#(Attr:0x3fda3ff45188 { name = "height", value = "100%" }),
#(Attr:0x3fda3ff45174 { name = "marginheight", value = "0px" }),
#(Attr:0x3fda3ff4514c { name = "marginwidth", value = "0px" })],
children = [ #(Text "Request unsuccessful. Incapsula incident ID: 245000650118470008-256430953704260629")]
})]
})]
})]
})
How can I achieve this web scraping?

Union operation in foreach object array (es6)?

I have to concat arrays in my object array with union operation. I have an object like below:
let appointments = [{
Name: "doctor",
Detail: [Place: "A street", Time: {
"10:10",
"15:00",
"15:30"
}]
}, {
Name: "hairdresser",
Detail: [Place: "B street", Time: {
"10:10",
"15:00",
"15:30"
}]
}, {
Name: "hairdresser",
Detail: [Place: "C street", Time: {
"10:10",
"15:00",
"15:30",
"14:00"
}]
}]
I want to concat time property at all details in one array with union.
It should be like below: How can I do that?
Time:["10:10","15:00","15:30","14:00"]
Extract all times to a new array, flatten it, then make it a Set to remove duplicates.
let appointments= [{Name:"doctor", Time:["10:10","15:00","15:30"]},{Name:"hairdresser", Time:["15:00","15:30"]}, {Name:"dentist", Time:["14:00"]}]
const time = [...new Set(appointments
.map(({Time}) => Time)
.reduce((all, item) => [...all, ...item]))]
console.log(time)
<script>
let appointments= [
{Name:"doctor", Time:["10:10","15:00","15:30"]},
{Name:"hairdresser", Time:["15:00","15:30"]},
{Name:"dentist", Time:["14:00"]}
]
var timeArray=[];
var lastArray=[]
appointments.forEach(function(item){
return timeArray.push(item.Time)
})
for (var i = timeArray.length - 1; i >= 0; i--) {
for (var j = timeArray[i].length - 1; j >= 0; j--) {
if(lastArray.indexOf(timeArray[i][j])===-1){
lastArray.push(timeArray[i][j])
}
}
}
console.log(lastArray)
</script>
This is just one method of doing it.

How to add table to table?

I want to add table 'mm' to table 'fmenu.pages' but it doesnt work at all. Error: attempt to index a nil value (field 'main2'). Its about last line. Code:
local fmenu = {
selected_button = 0,
menu = {
font = 1,
},
pages = {
["main"] = {
name = "name",
id = 1,
btns = {
{name = "name I", id = 1}
}
}
}
}
local mm = {
["main2"] = {
name = "name2",
id = 2,
btns = {
{name = "name I", id = 1},
{name = "name II", id = 2}
}
}
}
table.insert(fmenu.pages, mm)
print(fmenu.pages["main2"].name)
How about using table.merge from lua-stdlib?
local table = require"std.table"
local fmenu = {
selected_button = 0,
menu = {
font = 1,
},
pages = {
["main"] = {
name = "name",
id = 1,
btns = {
{name = "name I", id = 1}
}
}
}
}
local mm = {
["main2"] = {
name = "name2",
id = 2,
btns = {
{name = "name I", id = 1},
{name = "name II", id = 2}
}
}
}
table.merge(fmenu.pages, mm)
print(fmenu.pages["main2"].name)

JSON that contains an array to NSString

How do I extract each address from the NSDictionary I instantiated (below), so I can assign to various NSString objects?
I have the following JSON:
{
"Address":[
{
"$":{
"ID":"0"
},
"Address2":[
"10 Smith RD"
],
"City":[
"Mapleville"
],
"State":[
"NJ"
],
"Zip5":[
"90210"
],
"Zip4":[
"764"
]
},
{
"$":{
"ID":"1"
},
"Address2":[
"32 Hog CT"
],
"City":[
"New York City"
],
"State":[
"NY"
],
"Zip5":[
"90210"
],
"Zip4":[
"1390"
]
}
]
}
cData (below) came from the JSON above.
I did the following to convert to a NSDictionary:
NSDictionary* dictionary2 = [NSJSONSerialization JSONObjectWithData:cData options:NSJSONReadingAllowFragments error:nil];
once I did a:
NSLog(#"%#", dictionary2);
output from NSLog:
{
Address = (
{
"$" = {
ID = 0;
};
Address2 = (
"10 Smith RD"
);
City = (
"Mapleville"
);
State = (
NJ
);
Zip4 = (
7642
);
Zip5 = (
90210
);
},
{
"$" = {
ID = 1;
};
Address2 = (
"32 Hog CT"
);
City = (
"New York City"
);
State = (
NY
);
Zip4 = (
1390
);
Zip5 = (
90210
);
}
);
}
Just follow the structure.
NSDictionary* dictionary2 = [NSJSONSerialization ...
NSArray *addresses = dictionary2[#"Address"];
for (NSDictionary *addressData in addresses) {
NSString *address2 = addressData[#"Address2"];
NSString *city = addressData[#"City"];
// and the rest as needed
}

Resources