Find item from FileScanner by index in Groovy - collections

I am trying to find an item from a FileScanner (http://docs.groovy-lang.org/latest/html/api/org/codehaus/groovy/ant/FileScanner.html) for a given index in Groovy. The following closure works, but I am not sure how I can make it "return" the file name:
def getFileNameByIndex = { int fileIndex ->
scanner.eachWithIndex { fileName, index ->
if (index == fileIndex)
println "${index}. Filename ${fileName}"
// how do I return the fileName here?
}
}
I should be able to call it as: getFileNameByIndex(10), where 10 is the index.
Can someone please help?

Why not just do:
def getFileNameByIndex = { int fileIndex ->
list[fileIndex]?.fileName
}
As it's a scanner, not a list, I think you'd need:
def getFileNameByIndex = { int fileIndex ->
int idx = 0
scanner.find { idx++ == fileIndex }?.name
}

Related

Is there a way to modify the value inside a self referential structure using another pointer

Is there any way to store the value of the pointer inside a self-referential structure and then use it to modify the pointer instead of the structure it points to?
I'm trying to perform bst deletion using the following code:
struct node *temp = start;
struct node *parent = start;
int isRight = 0, flag = 0;
while(temp != NULL)
{
if(temp->data == key)
{
if(isRight == 1)
parent = parent->rlink;
else
parent = parent->llink;
if(temp->rlink != NULL)
{
if(temp->llink != NULL)
{
replace(temp->llink, temp->rlink);
}
parent = temp->rlink;
}
else if(temp->llink != NULL)
{
parent = temp->llink;
}
else
{
parent = NULL;
}
flag = 1;
break;
}
else if(temp->data < key)
{
parent = temp;
isRight = 1;
temp = temp->rlink;
}
else
{
parent = temp;
isRight = 0;
temp = temp->llink;
}
}
where:
void replace(struct node *temp, struct node *root)
{
while(root->llink != NULL)
{
root = root->llink;
}
root->llink = temp;
}
The problem is that parent = parent->llink/rlink just makes it so that the pointer parent points to the node that is in the parent->llink part of the node.
Is there any way to rewrite this code so that I can make the parent refer to the memory location inside the node parent which stores the link to the next node instead of the node itself?
I can rewrite this code to assign values directly to parent->llink/rlink by checking isRight for each case, but the code looks too clunky.
(This is not the actual way to perform bst deletion, but I'm trying to solve this on a whim.)

Finding a pair of elements in a Vec

Coming from another language I'm a little confused on how to do some basic stuff in Rust without breaking memory safety.
I'm trying to get references to a pair of elements stored in a Vec. Assume the elements stored in the Vec are large and I do not want to copy them:
struct Element {
key: u64,
data: SomeHugeType
}
In other languages (e.g. C++), I would just create two null pointers or something and loop over the vec like so:
const Element *ele1, *ele2;
ele1 = nullptr;
ele2 = nullptr;
for (auto const &ele : elements) {
if (ele.key == key1) { ele1 = ele; }
if (ele.key == key2) { ele2 = ele; }
if (ele1 != nullptr && ele2 != nullptr) { break; }
}
if (ele1 == nullptr || ele2 == nullptr) { /* uh oh */}
But as far as I know I cannot do this in rust because I cannot have a reference to nothing (nullptr). I cannot borrow an element before I know which element I need to borrow.
How can I initialize some variable ele1 and ele2 before I find the actual elements they should reference in the Vec?
To elaborate on Sebastian's answer, you can use None and Some(element) instead of nullptrs in C++:
type SomeHugeType = String;
struct Element {
key: u64,
data: SomeHugeType,
}
fn get_two_elems(elems: &Vec<Element>, key1: u64, key2: u64) -> Option<(&Element, &Element)> {
let (mut elem1, mut elem2) = (None, None);
for elem in elems {
if elem.key == key1 {
elem1 = Some(elem);
} else if elem.key == key2 {
elem2 = Some(elem)
}
if elem1.is_some() && elem2.is_some() {
break;
}
}
if let (Some(elem1), Some(elem2)) = (elem1, elem2) {
Some((elem1, elem2))
} else {
None
}
}
You can have a reference to nothing. It's just the type Option<T&>

Adding Array to plist (I can not see more than only one item on my plist)

import Foundation
struct answers : Codable {
var answer : String
var number : Int
}
var allAnswers: Array = [answers]()
let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let archiveURL = documentsDirectory.appendingPathExtension("answers_test").appendingPathExtension("plist")
class ViewController: UIViewController {
#IBOutlet var vcLabels: [UILabel]!
#IBOutlet weak var vcTextField: UITextField!
var index : Int = 0
#IBAction func vcButtonPressed(_ sender: Any) {
vcLabels[index].text = vcTextField.text
var newAnswer = answers(answer: vcLabels[index].text!, number: index)
var newAnswers = [newAnswer]
print(archiveURL)
index += 1
if index == 4 {
index = 0
}
let propertyListEncoder = PropertyListEncoder()
let encodedNotes = try? propertyListEncoder.encode(newAnswers)
try? encodedNotes?.write(to:archiveURL, options: .noFileProtection)
}
First of all please conform to the naming convention that struct and class names start with a capital letter, the benefit it that the struct Answer and the property answer cannot be mistaken. And to avoid more confusion name the struct in singular form (in the line where a new answer is created you are creating semantically one answer, not one answers). And the properties can be declared as constants (let).
struct Answer : Codable {
let answer : String
let number : Int
}
Your issue is very clear: If you want to append something to the property list file you have to read it first from archiveURL, append the item(s) and write it back.
#IBAction func vcButtonPressed(_ sender: Any) {
vcLabels[index].text = vcTextField.text
let newAnswer = Answer(answer: vcLabels[index].text!, number: index)
print(archiveURL)
index += 1
if index == 4 {
index = 0
}
do {
let data = try Data(contentsOf: archiveURL)
var savedAnswers = PropertyListDecoder().decode([answers], from: data)
savedAnswers.append(newAnswer)
let encodedNotes = try PropertyListEncoder().encode(savedAnswers)
try encodedNotes?.write(to:archiveURL, options: .noFileProtection)
} catch { print(error) }
}
And don't ignore errors with try?. Handle them

Count the number of nodes of a doubly linked list using recursion

Here is what I've done so far:
struct rep_list {
struct node *head;
struct node *tail;
}
typedef rep_list *list;
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
lst->head = lst->head->next;
return 1 + length(lst);
}
}
This works, but the head of the list the function accepts as a parameter gets changed. I don't know how to fix that.
I'm not allowed to change the function definition so it should always accept a list variable.
Any ideas?
EDIT: I tried to do what Tyler S suggested in the comments but I encountered another problem. If I create a node* variable at the beginning, it should point to lst->head. But then every recursive call to the function changes the value back to lst->head and I cannot move forward.
You don't need a local node: just don't change the list head. Instead, pass the next pointer as the recursion head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
return 1 + length(lst->head-next);
}
}
I see. Okay; this gets a bit clunky because of the chosen representation. You need a temporary variable to contain the remaining list. This iscludes changing the head.
int length(const list lst) {
if (lst->head == NULL) {
return 0;
}
else {
new_lst = new(list)
new_lst->head = lst->head->next;
var result = 1 + length(new_lst);
free(new_lst)
return result
}
}
At each recursion step, you create a new list object, point it to the 2nd element of the current list, and continue. Does this do the job for you?
Although this solution is clunky and I hate it, its the only way I can see to accomplish what you're asking without modifying the method signature. We create a temporary node * as member data of the class and modify it when we start.
struct rep_list {
struct node *head;
struct node *tail;
}
node *temp = NULL;
bool didSetHead = false;
typedef rep_list *list;
int length(const list lst) {
if ((didSetHead) && (lst->head != temp)) {
temp = lst->head;
didSetHead = false;
}
if (temp == NULL) {
didSetHead = true;
return 0;
}
else {
temp = temp->next;
return 1 + length(temp);
}
}
Please note, I haven't tested this code and you may have to play with a bit, but the idea will work.

QML item's children list deep copy

I'd like to make a deep copy of an items children property. I've tried things along the lines:
Item {
property variant itemsCopy
Component.onCompleted: {
var tmp = otherItem.children
itemsCopy = tmp
}
}
But when otherItem.children is changed (sorted due to different Z values), itemsCopy is also changed. Is there a workaround to break the binding or a way to prevent children from being sorted? I've tried Array s, list, nothing works. Changing members of tmp is ignored.
In the example provided by MartinJ all objects will be copied by reference. Here is a classic deep copy function from "Object-Oriented JavaScript" book:
function deepCopy(p, c) {
var c = c || {};
for (var i in p) {
if (typeof p[i] === 'object') {
c[i] = (p[i].constructor === Array) ? [] : {};
deepCopy(p[i], c[i]);
} else {
c[i] = p[i];
}
}
return c;
}
You could take a copy yourself:
import QtQuick 1.0
Item {
property variant itemsCopy
Component.onCompleted: {
var tmp = otherItem.children
var copy = []
for (var i = 0; i < tmp.length; ++i)
copy[i] = tmp[i]
itemsCopy = copy;
}
}
In QtQuick 2.0 it is a little easier as you can use property var:
import QtQuick 2.0
Item {
property var itemsCopy: []
Component.onCompleted: {
var tmp = otherItem.children
for (var i = 0; i < tmp.length; ++i)
itemsCopy[i] = tmp[i]
}
}

Resources