I am adding pagination to myTableview that presents blog posts. The data source is an array of posts, i.e. posts = [post].
I initially fetch 20 posts. I have a button that fetches the next 20 records. All of this is working fine. I can't figure how to insert these new records in the table without calling reloadData(). Can someone explain the following code? I don't understand what going on with the indexPaths on line 2 and 3 below.
On:
IndexPath(row:(self.posts.count - 1)
Am I passing the last row of the original dataset or the updated one?
TableView.beginUpdates()
let indexPath:IndexPath = IndexPath(row:(self.posts.count - 1), section:0)
TableView.insertRows(at: [indexPath], with: .left)
TableView.endUpdates()
If you want to add items to your tableview, the value passed to insertRows will be an array of index paths for the new rows in your model object:
let additionalPosts = ...
posts += additionalPosts
let indexPaths = (posts.count - additionalPosts.count ..< posts.count)
.map { IndexPath(row: $0, section: 0) }
tableView.insertRows(at: indexPaths, with: .left)
So, if you had 20 items in your array, and you add another 20 posts, the indexPaths would be:
[[0, 20], [0, 21], [0, 22], [0, 23], [0, 24], [0, 25], [0, 26], [0, 27], [0, 28], [0, 29], [0, 30], [0, 31], [0, 32], [0, 33], [0, 34], [0, 35], [0, 36], [0, 37], [0, 38], [0, 39]]
Related
I am facing one issue in the UITableViewDataSourcePrefetching implementation.
I have 62 records total in the cloud and I am calling the API which returns 15 records per page.
I have implemented the prefetchRowsAt method as well which partially works fine for me.
The issue is the above method does not return all the indexPath it is going to load so as you can see from below logs it goes up to 53 only and in my table view it shows 60 records only.
Indexpaths to fetch : [[3, 51], [3, 42], [3, 52], [3, 41], [3, 53], [3, 40], [3, 54], [3, 39], [3, 55], [3, 38], [3, 56], [3, 37], [3, 57], [3, 36], [3, 58], [3, 35], [3, 59], [3, 34], [3, 60], [3, 33]]
Indexpaths to fetch : [[3, 51], [3, 50], [3, 49], [3, 48], [3, 47], [3, 46], [3, 45], [3, 44], [3, 43]]
Indexpaths to fetch : [[3, 52]]
Indexpaths to fetch : [[3, 53]]
Here is my method implementation
extension MyViewController:UITableViewDataSourcePrefetching{
func tableView(_ tableView: UITableView, prefetchRowsAt indexPaths: [IndexPath]) {
#if DEBUG
print("Indexpaths to fetch : \(indexPaths)")
#endif
if indexPaths.contains(where: isLoadingCell) {
self.loadFurthersSessionNotification?()
}
}
}
private extension MyViewController {
func isLoadingCell(for indexPath: IndexPath) -> Bool {
if indexPath.section != 3{
return false
}
return (indexPath.row - 1) >= self.aryCloudObjects.count
}
}
Any help will be appreciated.
Thanks
There is nothing unexpected with the behaviour you are seeing. There is no guarantee that prefetchRowsAt will be called for every row in your table.
From the documentation:
Table views do not call this method for cells they require immediately, so your data source object must also be able to fetch the data itself.
Prefetching allows you to be prepared to display rows, but if the data hasn't been prefetched when cellForRowAt: is called then you need to fetch the data then.
I have a problem that I wonder if I can solve using cvxpy:
The problem:
I have a two dimensional integers array and I want to split it to two array in a way that each row of the source array is either in the 1st or 2nd array.
The requirement from these arrays us that for each column, the sum of integers in array #1 will be as close as possible to twice the sum of integers in array #2.
Example:
Consider the input array:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
The sums of its columns is [33, 30, 6, 29] so ideally we are looking for 2 arrays that the sums of their columns will be:
Array #1: [22, 20, 4, 19]
Array #2: [11, 10, 2, 10]
Off course this is not always possible but I looking for the best solution for this problem.
A possible solution for this specific example might be:
Array #1:
[
[1, 2, 3, 4],
[4, 6, 2, 5],
[8, 4, 0, 5],
[9, 8, 0, 4]
]
With column sums: [22, 20, 5, 18]
Array #2:
[
[3, 9, 1, 2],
[8, 1, 0, 9],
]
With column sums: [11, 10, 1, 11]
Any suggestions?
You can use a boolean vector variable to select rows. The only thing left to decide is how much to penalize errors. In this case I just used the norm of the difference vector.
import cvxpy as cp
import numpy as np
data = np.array([
[1, 2, 3, 4],
[4, 6, 2, 5],
[3, 9, 1, 2],
[8, 1, 0, 9],
[8, 4, 0, 5],
[9, 8, 0, 4]
])
x = cp.Variable(data.shape[0], boolean=True)
prob = cp.Problem(cp.Minimize(cp.norm((x - 2 * (1 - x)) * data)))
prob.solve()
A = np.round(x.value) # data
B = np.round(1 - x.value) # data
A and B are the sum of rows.
(array([21., 20., 4., 19.]), array([12., 10., 2., 10.]))
How can I sort the below array of dictionaries so that the keys of each dictionary are in ascending order, without creating anything new (using .sort not .sorted)? Any help is greatly appreciated, many thanks!!
Current array of dictionaries:
[[2: 0, 3: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0]]
What I would like:
[[1: 0, 2: 0, 3: 0], [1: 0, 2: 0], [1: 0, 2: 0], [1: 0, 2: 0]]
Code that isn't working:
var arrayOfDicts = [[2: 0, 3: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0]]
arrayOfDicts.sort(by: { $0.keys.first! > $1.keys.first! })
print(arrayOfDicts)
// prints [[2: 0, 3: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0], [2: 0, 1: 0]]
so that the keys of each dictionary are in ascending order
[[1: 0, 2: 0, 3: 0], [1: 0, 2: 0], [1: 0, 2: 0], [1: 0, 2: 0]]
To say "so that the keys of each dictionary are in ascending order" implies that you want to sort each actual dictionary (and that is what appears to be happening in your "what I would like" output). But a dictionary cannot be sorted; the notion is meaningless, because a dictionary has no order. The order in which its elements (or keys) are printed is random.
So what you're describing is impossible. You cannot want it. You may think you want it, but you don't. It would do you no good whatever; a "sorted" dictionary, if it existed, would change nothing, because it would not affect what the dictionary does, which is not to list elements in some order but to retrieve values by key.
Why is the structuring element asymmetric in OpenCV?
cv2.getStructuringElement(cv2.MORPH_ELLIPSE, ksize=(4,4))
returns
array([[0, 0, 1, 0],
[1, 1, 1, 1],
[1, 1, 1, 1],
[1, 1, 1, 1]], dtype=uint8)
Why isn't it
array([[0, 1, 1, 0],
[1, 1, 1, 1],
[1, 1, 1, 1],
[0, 1, 1, 0]], dtype=uint8)
instead?
Odd-sized structuring elements are also asymmetric with respect to 90-degree rotations:
array([[0, 0, 1, 0, 0],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[0, 0, 1, 0, 0]], dtype=uint8)
What's the purpose of that?
There's no purpose for it other than it's one of many possible interpolations for such a shape. In the case of the ellipse with size 5, if it were full it would just be the same as the MORPH_RECT and if the same two were removed from the sides as from the top it would be a diamond. Either way, the way it's actually implemented in the source code is what you would expect---it creates a circle via the distance function and takes near integers to get the binary pixels. Search that file for cv::getStructuringElement and you'll find the implementation, it's nothing too fancy.
If you think an update to this function should be made, then open up a PR on GitHub with the implemented version, or an issue to discuss it first. I think a successful contribution would be easy here and I'd venture that the case for symmetry is strong. One would expect the result of a symmetric image being processed with an elliptical kernel wouldn't depend on orientation of the image.
I'm using opencv and I'm able to get a pixel of an image-- a 3-dimensional tuple, via the code below. However, I'm not quite sure how to calculate the mode of the pixels values in the image.
import cv2
import numpy as np
import matplotlib.pyplot as plt
import numpy as np
import cv2
img =cv2.imread('C:\\Users\Moondra\ABEO.png')
#px = img[100,100] #gets pixel value
#print (px)
I tried,
from scipy import stats
stats.mode(img)[0]
But this returns an array shape of
stats.mode(img)[0].shape
(1, 800, 3)
Not sure how exactly stats is calculating the dimensions from which to choose the mode, but I'm looking for each pixel value (3 dimensional tuple) to be one element.
EDIT:
For clarity, I'm going to lay out exactly what I'm looking for.
Let's say we have an array that is of shape (3,5,3) and looks like this
array([[[1, 1, 2], #[1,1,2] = represents the RGB values
[2, 2, 2],
[1, 2, 2],
[2, 1, 1],
[1, 2, 2]],
[[1, 2, 2],
[2, 2, 2],
[2, 2, 2],
[1, 2, 2],
[1, 2, 1]],
[[2, 2, 1],
[2, 2, 1],
[1, 1, 2],
[2, 1, 2],
[1, 1, 2]]])
I would then convert it to an array that looks like this for easier calculation
Turn this into
array([[1, 1, 2],
[2, 2, 2],
[1, 2, 2],
[2, 1, 1],
[1, 2, 2],
[1, 2, 2],
[2, 2, 2],
[2, 2, 2],
[1, 2, 2],
[1, 2, 1],
[2, 2, 1],
[2, 2, 1],
[1, 1, 2],
[2, 1, 2],
[1, 1, 2]])
which is of shape(15,3)
I would like to calculate the mode by counting each set of RGB as follows:
[1,1,2] = 3
[2,2,2] = 4
[1,2,2] = 4
[2,1,1] = 2
[1,1,2] =1
Thank you.
From the description, it seems you are after the pixel that's occurring the most in the input image. To solve for the same, here's one efficient approach using the concept of views -
def get_row_view(a):
void_dt = np.dtype((np.void, a.dtype.itemsize * np.prod(a.shape[-1])))
a = np.ascontiguousarray(a)
return a.reshape(-1, a.shape[-1]).view(void_dt).ravel()
def get_mode(img):
unq, idx, count = np.unique(get_row_view(img), return_index=1, return_counts=1)
return img.reshape(-1,img.shape[-1])[idx[count.argmax()]]
We can also make use of np.unique with its axis argument, like so -
def get_mode(img):
unq,count = np.unique(img.reshape(-1,img.shape[-1]), axis=0, return_counts=True)
return unq[count.argmax()]
Sample run -
In [69]: img = np.random.randint(0,255,(4,5,3))
In [70]: img.reshape(-1,3)[np.random.choice(20,10,replace=0)] = 120
In [71]: img
Out[71]:
array([[[120, 120, 120],
[ 79, 105, 218],
[ 16, 55, 239],
[120, 120, 120],
[239, 95, 209]],
[[241, 18, 221],
[202, 185, 142],
[ 7, 47, 161],
[120, 120, 120],
[120, 120, 120]],
[[120, 120, 120],
[ 62, 41, 157],
[120, 120, 120],
[120, 120, 120],
[120, 120, 120]],
[[120, 120, 120],
[ 0, 107, 34],
[ 9, 83, 183],
[120, 120, 120],
[ 43, 121, 154]]])
In [74]: get_mode(img)
Out[74]: array([120, 120, 120])