I have two objects. One called EstimateItem and the other one is called Part (Part class is inherited from Realm's Object class). One EstimateItem can have multiple Parts.
class EstimateItem {
var parts: [Part]?
}
There's an array of EstimateItems with different numbers of Parts in each instance.
+--------------------------------+---------------------------------+
| EstimateItem | Parts |
+--------------------------------+---------------------------------+
| Line Item 1 - RnR WDH - Twins | Epoxy / Wood for lami |
| (single) | |
| | |
| Line Item 2 - RnR WDH - Twins | Epoxy / Wood for lami |
| (double) | |
| | |
|Line Item 3 - Install sash lock |Epoxy / Wood for lami / Sash lock|
+--------------------------------+---------------------------------+
I need to group them by specific Part. It should look something like this.
How do I do this?
I couldn't figure out a way to do this while the parts are attached to individual item so I tried laying them all out in an array of (part: Part, item: EstimateItem) tuples.
var groups = [(part: Part, item: EstimateItem)]()
for item in estimateItemsArray {
if let parts = item.parts {
for part in parts {
groups.append((part, item))
}
}
}
// Epoxy - RnR WDH - Twins (single)
// Wood for lami - RnR WDH - Twins (single)
// Epoxy - RnR WDH - Twins (double)
// Wood for lami - RnR WDH - Twins (double)
// Epoxy - RnR WDH - Twins (single)
// Wood for lami - RnR WDH - Twins (single)
// Sash lock, traditional - Install sash lock
And then group it.
But I'm still stuck. Also I feel like I'm overcomplicating it and I was wondering if there's an easier and more Swifty way of doing this.
What I came up with trying to find a more swifty way of doing this is the following:
let parts = Set(estimateItemsArray.flatMap{ $0.parts ?? [] })
let partMap = parts.map { part in
return (part, estimateItemsArray.filter {
$0.parts?.indexOf(part) != nil
}
)
}
partMap now contains tuples of the form (Part, [EstimateItem]). The only requirement is for Part to conform to Hashable or something related - in my test I just let Part inherit from NSObject.
Explanation:
create an array of all the available parts (Set to ensure uniqueness)
loop over the array mapping and returning a tuple of
the actual part
loop over estimateItemsArray filtering out the items that have the current part in their list
The complete test-data looks like this
/* the now classes, both include some identifier to distinguish them */
class Item {
var n : String
var parts : [Part]? = [Part]()
init(n:String) {
self.n = n
}
}
class Part : NSObject {
var n : String
init(n:String) {
self.n = n
}
}
/* set up the test data */
let item1 = Item(n: "item 1")
let item2 = Item(n: "item 2")
let item3 = Item(n: "item 3")
let part1 = Part(n: "part 1")
let part2 = Part(n: "part 2")
let part3 = Part(n: "part 3")
item1.parts = [part1, part2]
item2.parts = [part1, part3]
item3.parts = [part1, part2, part3]
var arrItems = [item1, item2, item3]
/* actual logic */
let parts = Set(arrItems.flatMap{ $0.parts ?? [] })
let partMap = parts.map { part in
return (part, arrItems.filter {
$0.parts?.indexOf(part) != nil
}
)
}
/* final output */
partMap.forEach { entry in
print("part \(entry.0.n)")
entry.1.forEach {
print("contains \($0.n)")
}
}
Outputting:
part part 1
contains item 1
contains item 2
contains item 3
part part 3
contains item 2
contains item 3
part part 2
contains item 1
contains item 3
If you cannot inherit from NSObject like I initially though, make your class Part conform to Hashable which is the requirement for sets:
class Part : Hashable {
var n : String
init(n:String) {
self.n = n
}
var hashValue: Int {
return n.hashValue // you basically have to provide some kind of logic based on *your* Part object
}
}
func ==(lhs: Part, rhs: Part) -> Bool {
return lhs.hashValue == rhs.hashValue
}
Related
I'm writing a recursive descent parser in Go for a simple made-up language, so I'm designing the grammar as I go. My parser works but I wanted to ask if there are any best practices for how I should lay out my code or when I should put code in its own function etc ... to make it more readable.
I've been building the parser by following the simple rules I've learned so far ie. each non-terminal is it's own function, even though my code works I think looks really messy and unreadable.
I've included the code for the assignment non-terminal and the grammar above the function.
I've taken out most of the error handling to keep the function smaller.
Here's some examples of what that code can parse:
a = 10
a,b,c = 1,2,3
a int = 100
a,b string = "hello", "world"
Can anyone give me some advice as to how I can make my code more readable please?
// assignment : variable_list '=' expr_list
// | variable_list type
// | variable_list type '=' expr_list
func (p *Parser) assignment() ast.Noder {
assignment := &ast.AssignmentNode{}
assignment.Left = p.variable_list()
// This if-statement deals with rule 2 or 3
if p.currentToken.Type != token.ASSIGN {
// Static variable declaration
// Could be a declaration or an assignment
// Only static variables can be declared without providing a value
assignment.IsStatic = true
assignment.Type = p.var_type().Value
assignment.Right = nil
p.nextToken()
// Rule 2 is finished at this point in the code
// This if-statement is for rule 3
if p.currentToken.Type == token.ASSIGN {
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
} else {
// This deals with rule 1
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
if assignment.Right == nil {
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
}
if len(assignment.Left) != len(assignment.Right) {
p.FoundError(p.syntaxError("variable mismatch, " + strconv.Itoa(len(assignment.Left)) + " on left but " + strconv.Itoa(len(assignment.Right)) + " on right,"))
}
return assignment
}
how I can make my code more readable?
For readability, a prerequisite for correct, maintainable code,
// assignment : variable_list '=' expr_list
// | variable_list type
// | variable_list type '=' expr_list
func (p *Parser) assignment() ast.Noder {
assignment := &ast.AssignmentNode{}
// variable_list
assignment.Left = p.variable_list()
// type
if p.currentToken.Type != token.ASSIGN {
// Static variable declaration
// Could be a declaration or an assignment
// Only static variables can be declared without providing a value
assignment.IsStatic = true
assignment.Type = p.var_type().Value
p.nextToken()
}
// '=' expr_list
if p.currentToken.Type == token.ASSIGN {
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
// variable_list [expr_list]
if assignment.Right == nil {
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
}
if len(assignment.Left) != len(assignment.Right) {
p.FoundError(p.syntaxError(fmt.Sprintf(
"variable mismatch, %d on left but %d on right,",
len(assignment.Left), len(assignment.Right),
)))
}
return assignment
}
Note: This likely inefficient and overly complicated:
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
What is the type of assignment.Right?
As far as how to make your code more readable, there is not always a cut and dry answer. I personally find that code is more readable when you can use function names in place of comments in the code. A lot of people like to recommend the book "Clean Code" by Robert C. Martin. He pushes this throughout the book, small functions that have one purpose and are self documenting (via the function name).
Of course, as I said before this is a subjective topic. I took a crack at it, and came up with the code below, which I personally feel is more readable. It also uses the function names to document what is going on. That way the reader doesn't necessarily need to dig into every single statement in the code, but rather just the high level function names if they don't need all of the details.
// assignment : variable_list '=' expr_list
// | variable_list type
// | variable_list type '=' expr_list
func (p *Parser) assignment() ast.Noder {
assignment := &ast.AssignmentNode{}
assignment.Left = p.variable_list()
// This if-statement deals with rule 2 or 3
if p.currentToken.Type != token.ASSIGN {
// Static variable declaration
// Could be a declaration or an assignment
// Only static variables can be declared without providing a value
p.parseStaticStatement(assignment)
} else {
p.parseVariableAssignment(assignment)
}
if assignment.Right == nil {
assignment.appendDefaultValues()
}
p.checkForUnbalancedAssignment(assignment)
return assignment
}
func (p *Parser) parseStaticStatement(assignment *ast.AssingmentNode) {
assignment.IsStatic = true
assignment.Type = p.var_type().Value
assignment.Right = nil
p.nextToken()
// Rule 2 is finished at this point in the code
// This if-statement is for rule 3
if p.currentToken.Type == token.ASSIGN {
a.parseStaticAssignment()
}
}
func (p *Parser) parseStaticAssignment(assignment *ast.AssignmentNode) {
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
func (p *Parser) parseVariableAssignment(assignment *ast.AssignmentNode) {
// This deals with rule 1
assignment.Operator = p.currentToken
p.nextToken()
assignment.Right = p.expr_list()
}
func (a *ast.AssignmentNode) appendDefaultValues() {
for i := 0; i < len(assignment.Left); i++ {
assignment.Right = append(assignment.Right, nil)
}
}
func (p *Parser) checkForUnbalancedAssignment(assignment *ast.AssignmentNode) {
if len(assignment.Left) != len(assignment.Right) {
p.FoundError(p.syntaxError("variable mismatch, " + strconv.Itoa(len(assignment.Left)) + " on left but " + strconv.Itoa(len(assignment.Right)) + " on right,"))
}
}
I hope that you find this helpful. I am more than willing to answer any further questions that you may have if you leave a comment on my response.
I have a processor which subscribes to publishers which arrive in arbitrary time. For each new subscriber to the processor, I want to emit the last item from each publisher.
class PublishersState {
val outputProcessor = DirectProcessor.create<String>()
fun addNewPublisher(publisher: Flux<String>) {
publisher.subscribe(outputProcessor)
}
fun getAllPublishersState(): Flux<String> = outputProcessor
}
val publisher1 = Mono
.just("Item 1 publisher1")
.mergeWith(Flux.never())
val publisher2 = Flux
.just("Item 1 publisher2", "Item 2 publisher2")
.mergeWith(Flux.never())
val publishersState = PublishersState()
publishersState.getAllPublishersState().subscribe {
println("Subscriber1: $it")
}
publishersState.addNewPublisher(publisher1)
publishersState.addNewPublisher(publisher2)
publishersState.getAllPublishersState().subscribe {
println("Subscriber2: $it")
}
I need to change the code above so it will output the following:
Subscriber1: Item 1 publisher1
Subscriber1: Item 1 publisher2
Subscriber1: Item 2 publisher2
// Subscriber2 subscribers here and receives the last item from each publisher
Subscriber2: Item 1 publisher1
Subscriber2: Item 2 publisher2
Is there a simple way to cache the last item for each publisher?
Use ReplayProcessor instead of DirectProcessor:
val outputProcessor = ReplayProcessor.cacheLast()
I solved my case the following way:
class PublishersState {
val publishersList = Collections.synchronizedList<Flux<String>>(mutableListOf()) // adding sync list for storing publishers
val outputProcessor = DirectProcessor.create<String>()
fun addNewPublisher(publisher: Flux<String>) {
val cached = publisher.cache(1) // caching the last item for a new publisher
publishersList.add(cached)
cached.subscribe(outputProcessor)
}
fun getAllPublishersState(): Flux<String> = publishersList
.toFlux()
.reduce(outputProcessor as Flux<String>) { acc, flux -> acc.mergeWith(flux.take(1)) } // merging the last item of each publisher with outputProcessor
.flatMapMany { it }
}
I have a series of animals in an array that I am joining via a ,.
However, I want the last animal to have an and before it, like so:
cow, giraffe, horse, mongoose, leopard, and snake.
The join method in Swift gives me everything except the and, and I am not sure how I can add any specifiers.
Sorry if this is a noob question, still getting the hang of this.
You could write you own join function like this:
func myjoin(separator: String, var elements:[String]) -> String {
elements[elements.count - 1] = "and " + elements[elements.count - 1]
return elements.joinWithSeparator(separator)
}
var animals = ["cow", "giraffe", "horse", "mongoose", "leopard", "snake"]
myjoin(", ", elements: animals)
Here's a version that does the "right thing" for lists with 1 or 2 elements:
func myjoin2(var elements:[String]) -> String {
let count = elements.count
let separator = (count == 2) ? " " : ", "
if count > 1 {
elements[count - 1] = "and " + elements[count - 1]
}
return elements.joinWithSeparator(separator)
}
myjoin2(["cat"]) // "cat"
myjoin2(["cat", "dog"]) // "cat and dog"
myjoin2(["cat", "dog", "pig"]) // "cat, dog, and pig"
I was solving a problem in which given a linked list of characters , we have to move the vowels to the beginning such that both vowels and consonants are in chronological order. That is in the order in which they appear in original list.
Input : S->T->A->C->K->O->V->E->R->F->L->O->W
Output : A->O->E->O->S->T->C->K->V->R->F->L->W
I did it by traversing through the list once and created two lists called vowels and consonants and later merged them.
Can it be done without creating extra lists ? I mean in-place maybe using pointer manipulation?
Remember the beginning of the list. When you meet a vowel, move it to the beginning of the list; the vowel becomes the new beginning that you remember.
1. Traverse the list
2. When you encounter a vowel, check with head if its smaller or greater
3. If smaller, re-place new vowel before head, else move head and check again
4. In the end relocate head to first
temp = head;
while(current.next != null) {
if(current.isVowel()) {
if(head.isVowel()) {
//check the precedence
//Re-place the current with temp
}
else {
//Re-place current in front of head
}
}
current = current.next;
}
This is an abstract understanding. Implement it properly.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
struct list {
struct list *next;
int ch;
};
#define IS_VOWEL(p) strchr("aeiouy", tolower(p->ch))
struct list *shuffle ( struct list *lst )
{
struct list *new=NULL, **dst, **src;
dst = &new;
for (src = &lst; *src; ) {
struct list *this;
this= *src;
if (!IS_VOWEL(this)) { src= &(*src)->next; continue; }
*src = this->next;
this->next = *dst;
*dst = this;
dst = & (*dst)->next;
}
*dst = lst;
return new;
}
int main (void)
{
struct list arr[] = { {arr+1, 'S'} , {arr+2, 'T'} , {arr+3, 'A'}
, {arr+4, 'C'} , {arr+5, 'K'} , {arr+6, 'O'}
, {arr+7, 'V'} , {arr+8, 'E'} , {arr+9, 'R'}
, {arr+10, 'F'} , {arr+11, 'L'} , {arr+12, 'O'} , {NULL, 'W'} };
struct list *result;
result = shuffle (arr);
for ( ; result; result = result->next ) {
printf( "-> %c" , result->ch );
}
printf( "\n" );
return 0;
}
OUTPUT:
-> A-> O-> E-> O-> S-> T-> C-> K-> V-> R-> F-> L-> W
You can quite easily modify pointers to create two independent lists without actually having to duplicate any of the nodes, which is what I assume you mean when you say you want to avoid creating new lists. Only the pointers in the original nodes are modified.
First let's create the structures for the list:
#include <stdio.h>
#include <stdlib.h>
// Structure for singly linked list.
typedef struct sNode {
char ch;
struct sNode *next;
} tNode;
And next we provide two utility functions, the first to append a character to the list:
// Append to list, not very efficient but debug code anyway.
static tNode *append (tNode *head, char ch) {
// Allocate new node and populate it.
tNode *next = malloc (sizeof (tNode));
if (next == NULL) {
puts ("Out of memory");
exit (1);
}
next->ch = ch;
next->next = NULL;
// First in list, just return it.
if (head == NULL)
return next;
// Else get last, adjust pointer and return head.
tNode *this = head;
while (this->next != NULL)
this = this->next;
this->next = next;
return head;
}
And the second to dump a list for debugging purposes:
// Debug code to dump a list.
static void dump (tNode *this) {
if (this == NULL)
return;
printf ("(%08x)%c", this, this->ch);
while ((this = this->next) != NULL)
printf (" -> (%08x)%c", this, this->ch);
putchar ('\n');
}
Beyond that, we need an easy way to tell if a node is a vowel or not. For our purposes, we'll only use uppercase letters:
// Check for vowel (uppercase only here).
static int isVowel (tNode *this) {
char ch = this->ch;
return (ch == 'A') || (ch == 'E') || (ch == 'I')
|| (ch == 'O') || (ch == 'U');
}
Now this is the important bit, the bit that turns the single list into two distinct lists (one vowel, one consonant). Which list is which type depends on what the first entry in the list is.
What is basically does is to create a sub-list out of all the common nodes at the start of the list ("ST" in this case), another sub-list of the next non-matching type ("A"), and then starts processing the remaining nodes one by one, starting with "C".
As each subsequent node is examined, the pointers are adjusted to add it to either the first or second list (again, without actually creating new nodes). Once we reach the NULL at then end of the list, we then decide whether to append the second list to the first, or vice versa (vowels have to come first).
The code for all this pointer manipulation is shown below:
// Meat of the solution, reorganise the list.
static tNode *regroup (tNode *this) {
// No reorg on empty list.
if (this == NULL)
return this;
// Find first/last of type 1 (matches head), first of type 2.
tNode *firstTyp1 = this, *firstTyp2 = this, *lastTyp1 = this, *lastTyp2;
while ((firstTyp2 != NULL) && (isVowel (firstTyp1) == isVowel (firstTyp2 ))) {
lastTyp1 = firstTyp2;
firstTyp2 = firstTyp2->next;
}
// No type 2 means only one type, return list as is.
if (firstTyp2 == NULL)
return firstTyp1;
// Type 2 list has one entry, next node after that is for checking.
lastTyp2 = firstTyp2;
this = firstTyp2->next;
//dump (firstTyp1);
//dump (firstTyp2);
//putchar ('\n');
// Process nodes until list is exhausted.
while (this != NULL) {
// Adjust pointers to add to correct list.
if (isVowel (this) == isVowel (lastTyp1)) {
lastTyp2->next = this->next;
lastTyp1->next = this;
lastTyp1 = this;
} else {
lastTyp1->next = this->next;
lastTyp2->next = this;
lastTyp2 = this;
}
// Advance to next node.
this = this->next;
//dump (firstTyp1);
//dump (firstTyp2);
//putchar ('\n');
}
// Attach last of one list to first of the other,
// depending on which is the vowel list.
if (isVowel (firstTyp1)) {
lastTyp1->next = firstTyp2;
return firstTyp1;
}
lastTyp2->next = firstTyp1;
return firstTyp2;
}
And, finally, no complex program would be complete without a test harness of some description, so here it is, something to create and dump the list in its initial form, then reorganise it and dump the result:
int main (void) {
char *str = "STACKOVERFLOW";
tNode *list = NULL;
while (*str != '\0')
list = append (list, *(str++));
dump (list);
puts("");
list = regroup (list);
dump (list);
return 0;
}
Upon entering, compiling and running all that code, the results are as expected:
(09c03008)S -> (09c03018)T -> (09c03028)A -> (09c03038)C ->
(09c03048)K -> (09c03058)O -> (09c03068)V -> (09c03078)E ->
(09c03088)R -> (09c03098)F -> (09c030a8)L -> (09c030b8)O ->
(09c030c8)W
(09c03028)A -> (09c03058)O -> (09c03078)E -> (09c030b8)O ->
(09c03008)S -> (09c03018)T -> (09c03038)C -> (09c03048)K ->
(09c03068)V -> (09c03088)R -> (09c03098)F -> (09c030a8)L ->
(09c030c8)W
In case that's hard to read, I'll get rid of the pointers and just list the characters in order:
S -> T -> A -> C -> K -> O -> V -> E -> R -> F -> L -> O -> W
A -> O -> E -> O -> S -> T -> C -> K -> V -> R -> F -> L -> W
I'm having issues grouping date range results in couch db.
Say I have this data:
2010-11-14, Tom
2010-11-15, Tom
2010-11-15, Dick
2010-11-15, Tom
2010-11-20, Harry
and i want use a view (and possibly reduce function) to return grouped names between 2010-11-14 and 2010-11-16, eg
Tom 3
Dick 1
how can this be
achieved?
I would suggest the following document structure, and map and reduce functions:
{ date : '2010-11-14', name : 'Tom' }
function(doc) { var r = {}; r[doc.name] = 1; emit (doc.date, r); }
function (keys, values, rereduce) {
var r = {};
for (var i in values) {
for (var k in values[i]) {
if (k in r) r[k] += values[i][k];
else r[k] = values[i][k];
}
}
return r;
}
Then, you would query the view, asking for a full reduce (no grouping) with startkey and endkey parameters 2010-11-14 and 2010-11-16. You will get in return a single value:
{ 'Tom': 3, 'Dick': 1 }