我在c#中定义了一个字符串数组
string[,] options = new string[100,3];
在整个代码中,它会填充数据,但并不总是填充。
因此,如果我有80个部分填充,20个部分未填充。 20个部分中包含空值或最后有60个空值。是否有一种简单的方法来调整数组的大小,以便在填充数组后,数组与
相同String[,] options = new string[80,3];
必须根据它找到的第一组3个零点的位置来调整大小。
如果这是一个锯齿状阵列,我会做的
options = options.Where(x => x != null).ToArray();
答案 0 :(得分:7)
这个方法很长,因为它必须检查每一行两次......
private static final long serialVersionUID = 1L;
@SuppressWarnings("unchecked")
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
resp.setContentType("application/json");
String action = req.getParameter("action");
try{
switch(action){
case "login":
AuthenticationActionsHandler authentication = new AuthenticationActionsHandler();
sendResponse(resp, authentication.logIn(req) );
break;
case "registration":
authentication = new AuthenticationActionsHandler();
sendResponse(resp, authentication.registration(req) );
break;
case "getName":
if((Integer) req.getSession().getAttribute("Id") != null){
UserActionsHandler user = new UserActionsHandler();
sendResponse(resp, user.getName(req) );
}
break;
case "logOut":
authentication = new AuthenticationActionsHandler();
sendResponse(resp, authentication.logOut(req) );
break;
case "search":
ActionsHandler searchAction = new ActionsHandler();
sendResponse(resp, searchAction.search(req) );
break;
case "saveRequest":
ActionsHandler saveRequestAction = new ActionsHandler();
sendResponse(resp, saveRequestAction.saveRequest(req) );
break;
case "showRequestedBooks":
HttpSession session = req.getSession(true);
Integer userId = (Integer)session.getAttribute("Id");
if(userId == null){
JSONObject result = new JSONObject();
result.put("authentication", false);
sendResponse(resp, result);
} else{
ActionsHandler showRequestedBooks = new ActionsHandler();
sendResponse(resp, showRequestedBooks.showRequestedItems(req) );
}
break;
}
}catch(MissingParameterException e){
sendErrorResponse(resp, e.getMissingParams());
}
}
public void sendResponse(HttpServletResponse resp, JSONArray resultJson ){
PrintWriter out;
try {
out = resp.getWriter();
out.println(resultJson);
} catch (IOException e) {
e.printStackTrace();
}
}
$("#login").click(function(){
var hashPassword = hex_md5($("#password").val());
var requestData = {
username: $('#username').val(),
password: hashPassword,
action: "login",
};
$.ajax({
type : "POST",
url : "/Library/dispatcher",
data : requestData,
}).done(
function(responseData){
if(responseData.error){
console.log(responseData.error);
$('#unsuccess').show();
}
else{
if(responseData.success){
// window.location.href = "/Library/search.html";
window.location.href = "/WEB-INF/search.html";
}
else{
$('#unsuccess').show();
}
}
});
});
使用它像:
public static string[,] RemoveEmptyRows(string[,] strs)
{
int length1 = strs.GetLength(0);
int length2 = strs.GetLength(1);
// First we count the non-emtpy rows
int nonEmpty = 0;
for (int i = 0; i < length1; i++)
{
for (int j = 0; j < length2; j++)
{
if (strs[i, j] != null)
{
nonEmpty++;
break;
}
}
}
// Then we create an array of the right size
string[,] strs2 = new string[nonEmpty, length2];
for (int i1 = 0, i2 = 0; i2 < nonEmpty; i1++)
{
for (int j = 0; j < length2; j++)
{
if (strs[i1, j] != null)
{
// If the i1 row is not empty, we copy it
for (int k = 0; k < length2; k++)
{
strs2[i2, k] = strs[i1, k];
}
i2++;
break;
}
}
}
return strs2;
}
根据阿列克谢的建议,还有另一种方法:
string[,] options = new string[100, 3];
options[1, 0] = "Foo";
options[3, 1] = "Bar";
options[90, 2] = "fiz";
options = RemoveEmptyRows(options);
这一点,在权衡记忆与时间的关系中,选择时间。它可能更快,因为它不必检查每一行两次,但它使用更多的内存,因为它将某些非空索引列入。
答案 1 :(得分:0)
我去了所有行,直到找到一个包含所有空值的行:
需要进行一些清理,并且显然会删除在第一个所有空行之后出现的非空行。这里的要求不太清楚
编辑:刚看到澄清要求删除所有空行的评论 - 我已经调整了以下内容以避免downvotes但是已经接受了更全面的答案(并且效率更高):)< / p>
void Main()
{
string[,] options = new string[100,3];
options[0,0] = "bleb";
options[1,1] = "bleb";
options[2,0] = "bleb";
options[2,1] = "bleb";
options[3,2] = "bleb";
options[4,1] = "bleb";
string[,] trimmed = TrimNullRows(options);
Console.WriteLine(trimmed);
}
public string[,] TrimNullRows(string[,] options)
{
IList<string[]> nonNullRows = new List<string[]>();
for (int x = 0; x < options.GetLength(0); x++)
{
bool allNull = true;
var row = new string[options.GetLength(1)];
for (int y = 0; y < options.GetLength(1); y++)
{
row[y] = options[x,y];
allNull &= options[x,y] == null;
}
if (!allNull)
{
nonNullRows.Add(row);
}
}
var optionsTrimmed = new string[nonNullRows.Count, options.GetLength(1)];
for (int i=0;i<nonNullRows.Count;i++)
{
for (int j=0;j<options.GetLength(1);j++)
{
optionsTrimmed[i, j] = nonNullRows[i][j];
}
}
return optionsTrimmed;
}
答案 2 :(得分:0)
linq的另一个变种
static string[,] RemoveNotNullRow(string[,] o)
{
var rowLen = o.GetLength(1);
var notNullRowIndex = (from oo in o.Cast<string>().Select((x, idx) => new { idx, x })
group oo.x by oo.idx / rowLen into g
where g.Any(f => f != null)
select g.Key).ToArray();
var res = new string[notNullRowIndex.Length, rowLen];
for (int i = 0; i < notNullRowIndex.Length; i++)
{
Array.Copy(o, notNullRowIndex[i] * rowLen, res, i * rowLen, rowLen);
}
return res;
}
答案 3 :(得分:0)
您还可以获得一些帮助,以便在锯齿状和多维表示之间进行转换。当然,这非常愚蠢,但是对于像你所展示的那些小的数组(以及非常稀疏的数组),它会很好。
void Main()
{
string[,] options = new string[100,3];
options[3, 1] = "Hi";
options[5, 0] = "Dan";
var results =
options
.JagIt()
.Where(i => i.Any(j => j != null))
.UnjagIt();
results.Dump();
}
static class Extensions
{
public static IEnumerable<IEnumerable<T>> JagIt<T>(this T[,] array)
{
for (var i = 0; i < array.GetLength(0); i++)
yield return GetRow(array, i);
}
public static IEnumerable<T> GetRow<T>(this T[,] array, int rowIndex)
{
for (var j = 0; j < array.GetLength(1); j++)
yield return array[rowIndex, j];
}
public static T[,] UnjagIt<T>(this IEnumerable<IEnumerable<T>> jagged)
{
var rows = jagged.Count();
if (rows == 0) return new T[0, 0];
var columns = jagged.Max(i => i.Count());
var array = new T[rows, columns];
var row = 0;
var column = 0;
foreach (var r in jagged)
{
column = 0;
foreach (var c in r)
{
array[row, column++] = c;
}
row++;
}
return array;
}
}
JagIt
方法当然非常简单 - 我们只是迭代行,yield
个别项目。这给了我们一个可枚举的枚举,我们可以很容易地在LINQ中使用它们。如果需要,您当然可以将它们转换为数组(例如,Select(i => i.ToArray()).ToArray()
)。
UnjagIt
方法更有说服力,因为我们需要先创建具有正确尺寸的目标数组。并且没有unyield
指令来简化:D
当然,这是非常低效的,但这不一定是个问题。例如,你可以通过保持内部可枚举为array
来保存自己的一些迭代 - 这将节省我们必须迭代所有内部项。
我主要将此作为内存便宜,CPU密集型替代@xanatos内存密集型,CPU便宜(相对)。
当然,主要的好处是它可以用来将任何多维数组视为锯齿状数组,然后再将它们转换回来。一般解决方案通常不是最有效的:D