Does GraphX support different types of vertices in the same graph? - spark-graphx

I'd like to know can I model a GraphX graph with different types of vertices? Say I have the following entities: product, buyer, seller. I want to form a graph structure with these entities as vertices. (eg: show graphically a product being sold by a seller and bought by a buyer.) Is it possible with GraphX and if so, how?
Thanks!

Of course.
A vertex is represented using an id and a set of properties, which can differ between vertices. Like so:
val vertices=Array(
( 1L, ( "1 property" ) ),
( 2L, ( "2 properties", 2 ) ),
( 3L, ( "3 properties", 3, true ) )
)
val vRDD= spark.parallelize( vertices )
val edges = Array(Edge(1L,2L,1800),Edge(2L,3L,800),Edge(3L,1L,1400))
val eRDD= spark.parallelize( edges )
val graph = Graph( vRDD, eRDD )
graph.vertices.collect.foreach( println )
You could use the first property of each vertex to denote what type of vertex it is.
Or you can use a more formal approach approach:
class VertexProperty()
case class DocumentProperty( val url: String ) extends VertexProperty
case class UserProperty( val name: String ) extends VertexProperty
case class SentenceProperty( val index: Int ) extends VertexProperty
val vertices = Array[ ( VertexId, VertexProperty) ] (
( 1L, DocumentProperty("www.bbc.co.uk") ),
( 2L, UserProperty("Sam") ),
( 3L, SentenceProperty( 1 ) )
)
val vRDD= spark.parallelize(vertices)
val edges = Array( Edge( 1L, 2L, 1800 ), Edge( 2L, 3L, 800 ), Edge( 3L, 1L, 1400 ) )
val eRDD= spark.parallelize(edges)
var graph: Graph[ VertexProperty, Int ] = Graph( vRDD, eRDD )
graph.vertices.collect.foreach {
case ( id, DocumentProperty( url ) ) => println( s"$url" )
case _ =>
}

Related

Instead of Scala Map objects, can we use any other proper objects for below type of structure?(Case Class)

I have just shifted to the scala and there I have the Map object as per the below structure.
object report {
def report_sn(flag : Boolean = false) : Map[String, Map[String,Any]] = Map(
"100"->Map("reportName"->"XYZ",
"queryColumns"->Array("title", "startDate", "endDate"),
"groupBy"->Array(),
"groupByFunctions"->Array(),
"query"->("SELECT * "+
"FROM "+
" abctable limit 10 "),
"queryParams"->Array(),
"xmlTemplate"->"xyz",
"processFunction"->"pqrFun"
),
"101"-> Map("reportName"->"XYZ1",
"queryColumns"->Array("title", "startDate", "endDate"),
"groupBy"->Array(),
"groupByFunctions"->Array(),
"query"->("SELECT * "+
"FROM "+
" abc1table limit 10 "),
"queryParams"->Array(),
"xmlTemplate"->"xyz1",
"processFunction"->"pqr1Fun"
)
)
Like this, I have 1000s of query details in this map object.
I am looking for a way to use some other objects to make it more readable and understandable code.
As commented by #LuisMiguelMejíaSuárez, you could use a case class instead of a Map[String, Any] and it will be more readable and better typed.
Something like this:
case class Report(reportName: String,
queryColumns: List[String],
groupBy: List[String],
groupByFunctions: List[String],
query: String,
queryParams: List[String],
xmlTemplate: String,
processFunction: String
)
def report_sn(flag: Boolean = false): Map[String, Report] =
Map(
"100" -> Report(
reportName = "XYZ",
queryColumns = List("title", "startDate", "endDate"),
groupBy = List(),
groupByFunctions = List(),
query = "SELECT * FROM abctable limit 10",
queryParams = List(),
xmlTemplate = "xyz",
processFunction = "pqrFun"
),
"101" -> Report(???)
)

Get indexes from one array and update elements on same indexes in second array

I have two arrays, upper and lower bound.
val solution : Array[Double] = Array(1.0, 33.0, 31.0, 82.0, 51.0, 25.0, 39.0, 96.0, 95.0, 49.0)
val original : Array[Double] = Array(3.0, 45.0, 18.0, 25.0, 99.0, 6.0, 36.0, 61.0, 82.0, 62.0)
val lower = 30
val upper = 90
Array of type Boolean is created using solution array.
val idx_lowest : Array[Boolean] = solution.map ( x => x < lower )
idx_lowest: Array[Boolean] = Array(true, false, false, false, false, true, false, false, false, false)
Find indexes in idx_lowest where value is true
val trueIndexes = idx_lowest .zipWithIndex filter(x => x._1 ) map(_._2)
trueIndexes: Array[Int] = Array(0, 5)
Find values against trueIndexes in original array.
val tmp = trueIndexes map original
Array[Double] = Array(3.0, 6.0)
Perform operation on elements of tmp array.
val tmp1 = tmp map (x => (x+lower)/2.0)
Array[Double] = Array(16.5, 18.0)
Update elements of solution array. Indexes are specified by trueIndexes. Elements those are less than lower bound are updated.
for(i <- tmp1.indices) {
solution(trueIndexes(i)) = tmp1(i)
}
The updated solution array is:
Array[Double] = Array(16.5, 33.0, 31.0, 82.0, 51.0, 18.0, 39.0, 96.0, 95.0, 49.0)
Same steps have to be performed to update elements that are greater than upper bound. Here is code.
val idx_false : Array[Boolean] = solution.map ( x => x > upper )
val falseIndexes = idx_false .zipWithIndex filter(x => x._1 ) map(_._2)
val tmp2 = falseIndexes map original
val tmp3 = tmp2 map (x => (x+upper)/2.0)
for(i <- tmp3.indices) {
solution(falseIndexes(i)) = tmp3(i)
}
solution
This code doing exactly what I needed but have to perform lot of operations. In iterative algorithm I have to perform these operation in each iteration for each array. Is there more efficient,optimal and faster way to perform same operation?
You can zip them and map in a single operation:
solution.zip(original)
.map { case(s, o) => if(s < lower) ((o + lower) / 2, o) else (s, o) }
.map { case(s, o) => if(s > upper) (o + upper) / 2 else s }
Isn't this the same result?
val done = solution.indices.map{x =>
if (solution(x) < lower) (lower + original(x))/2.0
else if (solution(x) > upper) (upper + original(x))/2.0
else solution(x)
}.toArray

Extending query arguments in graphene/graphene_django

How do I add non-field arguments to a GraphQL query in graphene? Here's an example of a use case. I'd like to be able to do:
{
hsv(h: 40, s: 128, v: 54) {
r
g
b
name
}
with this Django model:
from django.db import models
from django.core.validators import MinValueValidator, MaxValueValidator,
class Color(models.Model):
name = models.CharField(
"name",
max_length=24,
null=False, blank=False)
r = models.IntegerField(
"red", null=False, blank=False,
validators=[MinValueValidator(0), MinValueValidator(255)]
)
g = models.IntegerField(
"green", null=False, blank=False,
validators=[MinValueValidator(0), MinValueValidator(255)]
)
b = models.IntegerField(
"blue", null=False, blank=False,
validators=[MinValueValidator(0), MinValueValidator(255)]
)
and this GraphQL object type and Query based on it:
from graphene import ObjectType, IntegerField, Field, relay
from graphene_django import DjangoObjectType
from .django import Color
from colorsys import hsv_to_rgb
class ColorNode(DjangoObjectType):
r = IntegerField()
g = IntegerField()
b = IntegerField()
class Meta:
model = Color
class Query(ObjectType):
rgb = relay.node.Field(ColorNode)
hsv = relay.node.Field(ColorNode)
named = relay.node.Field(ColorNode)
def resolve_rgb(self, args, context, info):
if not all(map(lambda x: x in args, ['r', 'g', 'b'])):
# Arguments missing
return None
return Color.objects.get(**args)
def resolve_hsv(self, args, context, info):
if not all(map(lambda x: x in args, ['h', 's', 'v'])):
# Arguments missing
return None
r, g, b = hsv_to_rgb(args['h'], args['s'], args['v'])
return Color.objects.get(r=r, g=g, b=b)
def resolve_named(self, args, context, info):
if not 'name' in args:
# Arguments missing
return None
return Color.objects.get(name=args['name'])
It fails because the arguments aren't accepted. What am I missing?
The answer turns out to be simple. To add arguments to the resolver, declare the arguments in the constructor of the field, like this:
rgb = relay.node.Field(ColorNode,
r=graphene.String(),
g=graphene.String(),
b=graphene.String())
hsv = relay.node.Field(ColorNode,
h=graphene.String(),
s=graphene.String(),
v=graphene.String()))
named = relay.node.Field(ColorNode,
name=graphene.String())
The arguments may then be included in the query, as shown above.

create a class Table for an inexisting table slick scala (Slick 3.0.0, scala)

Assume that we have a database which contains two tables: Coffee and Suppliers and we have their corresponding case classes and tables, just as in the documentation:
import scala.slick.driver.MySQLDriver.simple._
import scala.slick.lifted.{ProvenShape, ForeignKeyQuery}
// A Suppliers table with 6 columns: id, name, street, city, state, zip
class Suppliers(tag: Tag) extends Table[(Int, String, String, String, String, String)](tag, "SUPPLIERS") {
def id: Column[Int] = column[Int]("SUP_ID", O.PrimaryKey) // This is the primary key column
def name: Column[String] = column[String]("SUP_NAME")
def street: Column[String] = column[String]("STREET")
def city: Column[String] = column[String]("CITY")
def state: Column[String] = column[String]("STATE")
def zip: Column[String] = column[String]("ZIP")
// Every table needs a * projection with the same type as the table's type parameter
def * : ProvenShape[(Int, String, String, String, String, String)] = (id, name, street, city, state, zip)
}
// A Coffees table with 5 columns: name, supplier id, price, sales, total
class Coffees(tag: Tag) extends Table[(String, Int, Double, Int, Int)](tag, "COFFEES") {
def name: Column[String] = column[String]("COF_NAME", O.PrimaryKey)
def supID: Column[Int] = column[Int]("SUP_ID")
def price: Column[Double] = column[Double]("PRICE")
def sales: Column[Int] = column[Int]("SALES")
def total: Column[Int] = column[Int]("TOTAL")
def * : ProvenShape[(String, Int, Double, Int, Int)] = (name, supID, price, sales, total)
// A reified foreign key relation that can be navigated to create a join
def supplier: ForeignKeyQuery[Suppliers, (Int, String, String, String, String, String)] =
foreignKey("SUP_FK", supID, TableQuery[Suppliers])(_.id)
}
Now assume that we want to do a join:
val result = for {
c <- coffees
s <- suppliers if c.supID === s.id
} yield (c.name, s.name)
And here dealing with the result is complicated ( and it's more complicated if we have a lot of joins) because we need always to remember the order of names, to know what _._1 or _._2 refer to ... etc.
Question 1 Is there a way to change the type of the result as a table of a new class which contains the desired columns ?
Question 2 Here is a way but I can't finish it, we construct a case class for example:
case class Joined(nameS: String,nameC: String)
and after that we construct the corresponding table which I don't know how
class Joineds extends Table[Joinedclass] {
//Todo
}
and when we write a join we can write something like ( so that we can transform result to a type Joined) :
val result = for {
c <- coffees
s <- suppliers if c.supID === s.id
} yield (c.name, s.name).as(Joinds)
Thank you.
Can you define it like:
val result = for {
c <- coffees
s <- suppliers if c.supID === s.id
} yield Joined(c.name, s.name)
And the tuck it away in some convenient place?

Condition for while loop not working, unable to populate tableview cells

I'm a beginner to ios and am building my first app...so go easy on me :-)
I am trying to display the results from a web service in tableview cells. However my while loop condition is failing. I moved the nslog into the while loop and it clearly prints the objects in the array as you would expect. However there is something wrong when it ends I believe.
Does anyone have any ideas as to why it is failing?
Basically I'm trying to get 'Recipe name' and 'smallImageUrls; from the web service results and print that in a tableview cell.
I know my tableview cell wont print properly as is. I'll address that in a bit. Probably extract the urls into one array and then use that array to in the tableviewcell method.
Any assistance anyone can provide is greatly appreciated. I just find it strange as it is clearly going through the while loop without any issues. :-S
No real error message just:
self SearchedYummlyViewController * 0x12b39570
matchesCount int 40
in the left part of the pane at the bottom.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
self.searchYummlyRecipeResults = [NSJSONSerialization JSONObjectWithData:self.yummlyRecipesNSData options:nil error:nil];
self.tempYummlyResultsMatches = [[NSMutableArray alloc]init];
int matchesCount = 0;
while([self.searchYummlyRecipeResults[#"matches"]objectAtIndex:matchesCount]){
[self.tempYummlyRecipeMatch addObject:[[self.searchYummlyRecipeResults[#"matches"]objectAtIndex:matchesCount]objectForKey:#"recipeName"]];
[self.tempYummlyRecipeMatch addObject:[[self.searchYummlyRecipeResults[#"matches"]objectAtIndex:matchesCount]objectForKey:#"smallImageUrls"]];
NSLog(#"tempYummlyRecipeMatch array's contents: %#", self.tempYummlyRecipeMatch);
matchesCount++;
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
// Configure the cell...
NSString *recipeString = self.tempYummlyRecipeMatch[indexPath.row];
cell.textLabel.text = recipeString;
//The below is code on how to add a image from a web service to a cell. I dont think that will work but my code cant make it down there yet so I'll tackle that after while loop issue.
NSURL *url = [NSURL URLWithString:self.tempYummlyRecipeMatch[indexPath.row+1];
UIImage *image = [UIImage imageWithData: [NSData dataWithContentsOfURL:url]];
cell.imageView.image = image;
return cell;
}
Example of the webservice output below:
Recipe List: {
attribution = {
html = "<a href='http://www.yummly.com/recipes/onion-soup'>onion soup recipes</a> search powered by <img src='http://static.yummly.com/api-logo.png'/>";
logo = "http://static.yummly.com/api-logo.png";
text = "onion soup recipes: search powered by Yummly";
url = "http://www.yummly.com/recipes/onion-soup";
};
criteria = {
allowedIngredients = (
);
excludedIngredients = (
);
facetFields = (
);
maxResults = 6;
requirePictures = 0;
resultsToSkip = 0;
terms = (
onion,
soup
);
};
facetCounts = {
};
matches = (
{
attributes = {
};
flavors = {
bitter = "0.1666666666666667";
meaty = "0.3333333333333333";
piquant = 0;
salty = "0.5";
sour = "0.3333333333333333";
sweet = "0.5";
};
id = "French-onion-soup-sandwiches-309090";
ingredients = (
"olive oil",
"sea salt",
"fresh thyme leaves",
"granulated sugar",
"yellow onions",
"unsalted butter",
"beef broth",
"cracked black pepper",
"gruyere cheese",
bread
);
rating = 0;
recipeName = "French Onion Soup Sandwiches";
smallImageUrls = (
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
);
sourceDisplayName = "Joy the Baker";
totalTimeInSeconds = 0;
},
{
attributes = {
course = (
"Main Dishes"
);
};
flavors = {
bitter = 1;
meaty = "0.1666666666666667";
piquant = 0;
salty = 1;
sour = "0.1666666666666667";
sweet = "0.3333333333333333";
};
id = "Awesome-Slow-Cooker-Pot-Roast-Allrecipes";
ingredients = (
"condensed cream of mushroom soup",
"onion soup mix",
"pot roast",
water
);
rating = "4.69";
recipeName = "Awesome Slow Cooker Pot Roast";
smallImageUrls = (
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
);
sourceDisplayName = AllRecipes;
totalTimeInSeconds = 29400;
},
{
attributes = {
course = (
Soups,
Appetizers
);
cuisine = (
French
);
holiday = (
Thanksgiving
);
};
flavors = {
bitter = "0.1666666666666667";
meaty = "0.1666666666666667";
piquant = 0;
salty = "0.1666666666666667";
sour = "0.1666666666666667";
sweet = "0.1666666666666667";
};
id = "French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364";
ingredients = (
"stick butter",
"french bread",
"yellow onion",
"low sodium chicken broth",
"gruyere cheese",
"minced garlic",
"dry white wine",
"worcestershire sauce",
"beef broth"
);
rating = 0;
recipeName = "French Onion Soup";
smallImageUrls = (
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1512.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1199.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-220.s.jpg"
);
sourceDisplayName = "The Pioneer Woman";
totalTimeInSeconds = 0;
},
{
attributes = {
course = (
Soups
);
};
flavors = "<null>";
id = "Curried-sweet-potato-soup-333086";
ingredients = (
broth,
salt,
"sweet potatoes",
"lite coconut milk",
onion,
"coconut oil",
"curry powder",
garlic,
spinach,
lime,
"chopped cilantro",
"red pepper flakes",
"brown sugar",
peas
);
rating = 0;
recipeName = "Curried Sweet Potato Soup";
smallImageUrls = (
"http://i.yummly.com/Curried-sweet-potato-soup-333086-295006.s.jpg"
);
sourceDisplayName = "Camille Styles";
totalTimeInSeconds = 0;
},
{
attributes = {
};
flavors = "<null>";
id = "French-onion-soup-grilled-cheese-308496";
ingredients = (
"unsalted butter",
"kosher salt",
"sweet onions",
"unsalted beef stock",
pepper,
"gruyere cheese",
"dry sherry",
"italian bread",
"fresh thyme"
);
rating = 0;
recipeName = "French Onion Soup Grilled Cheese";
smallImageUrls = (
"http://i.yummly.com/French-onion-soup-grilled-cheese-308496-272505.s.jpg"
);
sourceDisplayName = "The Kitchn";
totalTimeInSeconds = 0;
},
{
attributes = {
};
flavors = {
bitter = 1;
meaty = 1;
piquant = 0;
salty = 1;
sour = 1;
sweet = "0.8333333333333334";
};
id = "Vidalia-onion-soup-with-wild-rice-and-blue-cheese-305366";
ingredients = (
"vidalia onions",
"chicken stock",
herb,
pepper,
"wild rice",
"unsalted butter",
baguette,
salt,
"extra virgin olive oil",
other
);
rating = 0;
recipeName = "Vidalia Onion Soup with Wild Rice and Blue Cheese";
smallImageUrls = (
"http://i.yummly.com/Vidalia-onion-soup-with-wild-rice-and-blue-cheese-305366-268824.s.jpg"
);
sourceDisplayName = "Smitten Kitchen";
totalTimeInSeconds = 0;
},
Example of tempYummlyRecipeResults nslog
tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
)
)
2013-02-27 22:13:34.334 CustomTableView[435:11303] tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
),
"Awesome Slow Cooker Pot Roast",
(
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
)
)
2013-02-27 22:13:34.335 CustomTableView[435:11303] tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
),
"Awesome Slow Cooker Pot Roast",
(
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
),
"French Onion Soup",
(
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1512.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1199.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-220.s.jpg"
)
)
2013-02-27 22:13:34.335 CustomTableView[435:11303] tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
),
"Awesome Slow Cooker Pot Roast",
(
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
),
"French Onion Soup",
(
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1512.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1199.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-220.s.jpg"
),
"Curried Sweet Potato Soup",
(
"http://i.yummly.com/Curried-sweet-potato-soup-333086-295006.s.jpg"
)
)
2013-02-27 22:13:34.335 CustomTableView[435:11303] tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
),
"Awesome Slow Cooker Pot Roast",
(
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
),
"French Onion Soup",
(
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1512.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1199.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-220.s.jpg"
),
"Curried Sweet Potato Soup",
(
"http://i.yummly.com/Curried-sweet-potato-soup-333086-295006.s.jpg"
),
"French Onion Soup Grilled Cheese",
(
"http://i.yummly.com/French-onion-soup-grilled-cheese-308496-272505.s.jpg"
)
)
2013-02-27 22:13:34.335 CustomTableView[435:11303] tempYummlyRecipeMatch array's contents: (
"French Onion Soup Sandwiches",
(
"http://i.yummly.com/French-onion-soup-sandwiches-309090-273265.s.jpg"
),
"Awesome Slow Cooker Pot Roast",
(
"http://i2.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-2.s.png",
"http://i.yummly.com/Awesome-Slow-Cooker-Pot-Roast-Allrecipes-58919.s.png"
),
"French Onion Soup",
(
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1512.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-1199.s.jpg",
"http://i.yummly.com/French-Onion-Soup-The-Pioneer-Woman-Cooks-_-Ree-Drummond-41364-220.s.jpg"
),
"Curried Sweet Potato Soup",
(
"http://i.yummly.com/Curried-sweet-potato-soup-333086-295006.s.jpg"
),
"French Onion Soup Grilled Cheese",
(
"http://i.yu
At the end of your connectionDidFinishLoading, you should reload your table view.
[self.tableView reloadData];
Just updating your array does not instantly update your table view.
EDIT: You are right, your while loop condition is incorrect. Currently, it only checks if the object at index matchesCount is not nil (somewhat similar to while(object) or while(object != nil)). I think what you are looking for is if the number of objects in the array is greater than matchesCount so as to prevent an array index out of bounds exception. To do so, you need to use while([self.searchYummlyRecipeResults[#"matches"] count] > matchesCount).

Resources