外推算法填充2D数组的边界单元 [英] Extrapolation algorithm to fill border cell of a 2D array

查看:91
本文介绍了外推算法填充2D数组的边界单元的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试填充2D数组中的空白单元格.我想在2D数组的边框中填充行和列.

例如,我的实际2D数组是这样的

  0   0   0   0   0   0 
 0   2   3   2   0   2   3   2   0   3   2   1   0   4   3   2   0   0   0   0  解决方案

请参阅我对问题的评论.

最简单的线性外推算法很简单.

首先,您的所有单元格都不为空.假设0个单元格为空",但您不应将其表示为0,因为您必须在0(作为有效数字)和"no value(无值)"之间进行区分.无论如何……例如,让我们考虑第二条水平线"0 2 3 3 2 0".让我使用一些伪图形在图形上显示它:

 | | |
  | | | |
  | | | |
0 1 2 3 4 5 

此处,水平的数字行代表水平行中单元格的索引,|条形表示每个单元格中的值.现在,线性外推意味着您可以在图形上绘制一条连接点的直线,并继续最左边和最右边的线段与X轴相交.实际上,它使简单的线性方程式

 f(x)= A + B * x 


您有两个点,f(1)= 2和f(2)= 3,因此方程式的解为f(0)= 1.
同样,f(5)= 1,由两个值f(3)和f(4)确定.如您所见,在确定f(0)时只涉及最左边的两个点,而在确定f(5)时只涉及最右边的两个点.

以相同的方式,找出每一行的值,并以相同的方式,找出每一列的值.

—SA


如果您希望操纵各种类型的二维对象数组的边缘单元",请采取以下策略: lang ="C#"> // 必需 使用 System.Collections.Generic; 使用 System.Linq; 公共 无效 Set2DArrayValues< T>( ref T [,] theAry,Func< int, int ,T> arrayValueSetter) { 如果(theAry == )返回 ; 如果(xfunc == )返回 ; int dim0 = theAry.GetLength( 0 ); 如果(dim0 == 0 )返回 ; int dim1 = theAry.GetLength( 1 ); 如果(dim1 == 0 )返回 ; for ( int i = 0 ; i < dim0; i ++) { for ( int j = 0 ; j < dim1; j ++) { theAry [i,j] = arrayValueSetter(i,j); } } }

这是一个通用方法,它传递了一个任意类型(T)的二维数组,以及一个接受两个整数参数并返回一个T型对象的Func(Function).
这是您如何使用它来创建一个6x6的字符串数组的示例,该数组在所有边缘"单元格中都为零,非边缘单元格设置为String.Empty:

 私有 strAry [,];

私有 无效 SampleUsage()
{
    // 初始化
    strAry =  字符串 [ 6  6 ];

    // 获取数组边界
     int  dim0 = strAry.GetLength( 0 )- 1 ;
     int  dim1 = strAry.GetLength( 1 )- 1 ;

    // 定义转换函数
    Func< int, int ,字符串> stringValueSetter =(i1,i2)= > 
    {
        返回(i1 ==  0  || i1 == dim0 || i2 == " 
            :字符串 .Empty;
    };

    // 使用预定义的Func'stringValueSetter 
    // 将边缘单元设置为"0"; String.Empty的非边缘单元格
    Set2DArrayValues< string>( ref  strAry,stringValueSetter);
}

// 输出(现在在此处显示由代码插入的逗号)
//  0,0,0,0,0,0,
//  0,,,,,0,
//  0,,,,,0,
//  0,,,,,0,
//  0,,,,,0,
//  0,0,0,0,0,0  

另一个示例:如果我们已经创建了一个Integer 2-d数组,并且希望矩阵中的对角线是矩阵行号的平方,并且所有其他像元都设置为#0:

int[,] intAry = new int[6,6];

// note we don''t use the Array bounds here

Set2DArrayValues<int>(ref intAry, (i1, i2) =>
{
    return (i1 == i2)
        ? i1*i2 // arbitrary computation
        : 0;
});

请注意,这里我们定义了必要的Func( )直接使用lambda表达式.

但是,如果我们想做的不仅仅是设置"值,那该怎么办?如果我们要转换数组中的现有值怎么办?为此,只需对上述内容进行较小的修改:

  public   void  Transform2DArrayValues< T>( ref  T [,] theAry,Func<  int  int ,T> xtfunc)
{
    如果(theAry == )返回 ;
    如果(xtfunc == )返回 ;

     int  dim0 = theAry.GetLength( 0 );
    如果(dim0 ==  0 )返回 ;

     int  dim1 = theAry.GetLength( 1 );
    如果(dim1 ==  0 )返回 ;

     for ( int  i =  0 ; i <  dim0; i ++)
    {
         for ( int  j =  0 ; j <  dim1; j ++)
        {
            theAry [i,j] = xtfunc(theAry [i,j],i,j);
        }
    }
} 

现在,我们传递的Func(函数)将在单元格中包含当前值;我们可以以某种方式使用它,也可以忽略它.例如:

  int  dim0 =  6 ;
 int  dim1 =  6 ;

字符串 [,] strAry2 =  字符串 [dim0,dim1];

strAry2 [ 1  2 ] = " 培根";
strAry2 [ 3  4 ] = " 培根";

// 请注意,此处我们不使用数组边界

Func< string, int  int ,string> stringArrayValueTransform =(str,i1,i2)= > 
{
    如果(str == "  )返回 " ;

    如果(i1 ==  0 )返回 " ;

    如果(i1%5 ==  0 )
        返回(i2%2 ==  0 )
            ? " 
            :" ;

    返回 "  ;
};

// 转换数组; 
Transform2DArrayValues( ref  strAry2,stringArrayValueTransform);

// 显然是一个愚蠢的示例:

//  Bob,Bob,Bob,Bob,Bob,Bob和
// 投票#5 :),投票#5 :),仓鼠,投票#5 :),投票#5: ),投票5 :),
// 投票#5 :),投票#5 :),投票#5 :),投票#5 :),投票#5 :),投票#5 :),
// 投票#5 :),投票#5 :),投票#5 :),投票#5 :),仓鼠,投票#5 :),
// 投票#5 :),投票#5 :),投票#5 :),投票#5 :),投票#5 :),投票#5 :),
//  OriginalGriff,Sheep,OriginalGriff,Sheep,OriginalGriff,Sheep, 


I am trying to fill empty cells in the 2D array. I want to fill rows and columns in the border of a 2D array.

Eg My actual 2D array like this

0 0 0 0 0 0
0 2 3 3 2 0
0 2 3 4 2 0
0 3 2 3 1 0
0 4 3 4 2 0
0 0 0 0 0 0



In this I want to fill those zeros with some values. I am trying to an extrapolation method to fill this. But I am not getting how to do this in my 2D array.


I want to generate an (N+2) by (N+2) array from NbyN matrix using extrapolation.

What I have tried:

I tried to average of nearest and searched in net for extrapolation algorithm to fill the empty cell in border.

解决方案

Please see my comment to the question.

The simplest linear extrapolation algorithm is, well… simple.

First of all, none of your cells are empty. Let''s assume that 0 cells are "empty", but you should not denote them with 0, because you have to make difference between 0 as a valid number and "no value". Anyway… For example, let''s consider second horizontal line "0 2 3 3 2 0". Let me show it on a graph, using some pseudo-graphics:

    | |
  | | | |
  | | | |
0 1 2 3 4 5

Here, horizontal row of number represent the index of a cell in a horizontal row, and | bars represent the value in each cell. Now, linear extrapolation means that you draw a straight line connecting points on a graph, and continue the leftmost and rightmost line segment to intersect with X axes. Actually, it makes the simple linear equation

f(x) = A + B*x


You have two points, f(1)=2 and f(2)=3, so the solution of the equation gives you f(0)=1.
Likewise, f(5)=1, determined by two values, f(3) and f(4). As you can see, only two leftmost points are involved in determination of f(0), and only two rightmost points — in determination of f(5).

The same way, find out the values for each row, and, in the same way, for each column.

—SA


If you wish to manipulate the "edge cells" of a 2 dimensional Array of objects of various Types, here''s one strategy:

// required
using System.Collections.Generic;
using System.Linq;

public void Set2DArrayValues<T>(ref T[,] theAry, Func<int, int, T> arrayValueSetter)
{
    if (theAry == null) return;
    if (xfunc == null) return;

    int dim0 = theAry.GetLength(0);
    if (dim0 == 0) return;

    int dim1 = theAry.GetLength(1);
    if (dim1 == 0) return;

    for (int i = 0; i < dim0; i++)
    {
        for (int j = 0; j < dim1; j++)
        {
            theAry[i,j] = arrayValueSetter(i, j);
        }
    }
}

This a generic Method which gets passed a 2-dimensional Array of arbitrary Type (T), and a Func (Function) that takes two integer arguments, and returns an object of Type T.

Here''s how you could use it to create a 6x6 Array of String with zeroes in all the "edge" cells, and the non-edge cells set to String.Empty:

private strAry[,];

private void SampleUsage()
{
    // initialize
    strAry = new string[6,6];

    // get the array bounds
    int dim0 = strAry.GetLength(0) - 1;
    int dim1 = strAry.GetLength(1) - 1;

    // define a transformation function
    Func<int, int, string> stringValueSetter = (i1, i2) =>
    {
        return (i1 == 0 || i1 == dim0 || i2 == 0 || i2 == dim1)
            ? "0"
            : String.Empty;
    };

    // uses pre-defined Func 'stringValueSetter
    // sets the edge cells to "0"; the non-edge cells to String.Empty
    Set2DArrayValues<string>(ref strAry, stringValueSetter);
}

// output (commas inserted by code now shown here)
//0,	0,	0,	0,	0,	0,	
//0,	,	,	,	,	0,	
//0,	,	,	,	,	0,	
//0,	,	,	,	,	0,	
//0,	,	,	,	,	0,	
//0,	0,	0,	0,	0,	0

Another example: if we had created an Integer 2-d array, and wanted the diagonals in the matrix to be the square of the matrix row number, and all other cells to be set to #0:

int[,] intAry = new int[6,6];

// note we don''t use the Array bounds here

Set2DArrayValues<int>(ref intAry, (i1, i2) =>
{
    return (i1 == i2)
        ? i1*i2 // arbitrary computation
        : 0;
});

Note that here we define the necessary Func (function) directly by using a lambda expression.

But, what if we want to do more than just "set" values; what if we''d like to transform existing values in the Array? To do that requires only a minor modification to the above:

public void Transform2DArrayValues<T>(ref T[,] theAry, Func<T, int, int, T> xtfunc)
{
    if (theAry == null) return;
    if (xtfunc == null) return;

    int dim0 = theAry.GetLength(0);
    if (dim0 == 0) return;

    int dim1 = theAry.GetLength(1);
    if (dim1 == 0) return;

    for (int i = 0; i < dim0; i++)
    {
        for (int j = 0; j < dim1; j++)
        {
            theAry[i, j] = xtfunc(theAry[i,j], i, j);
        }
    }
}

Now, the Func (function) we pass will contain the current value in the cell; we can use that in some way, or ignore it. For example:

int dim0 = 6;
int dim1 = 6;

string[,] strAry2 = new string[dim0,dim1];

strAry2[1, 2] = "Bacon";
strAry2[3, 4] = "Bacon";

// note we do not use the Array bounds here

Func<string, int, int, string> stringArrayValueTransform = (str, i1, i2) =>
{
    if (str == "Bacon") return "Hamster";

    if (i1 == 0) return "Bob";

    if (i1%5 == 0)
        return (i2%2 == 0)
            ? "OriginalGriff"
            : "Sheep";

    return "Vote this up :)";
};

// Transform the Array;
Transform2DArrayValues(ref strAry2, stringArrayValueTransform);

// Obviously a silly example:

//Bob,	Bob,	Bob,	Bob,	Bob,	Bob,	
//Vote #5 :),	Vote #5 :),	Hamster,	Vote #5 :),	Vote #5 :),	Vote #5 :),	
//Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	
//Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	Hamster,	Vote #5 :),	
//Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	Vote #5 :),	
//OriginalGriff,	Sheep,	OriginalGriff,	Sheep,	OriginalGriff,	Sheep,


这篇关于外推算法填充2D数组的边界单元的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆